From 420f7ac6adb82486e6278e0f8dd961b1d6768637 Mon Sep 17 00:00:00 2001 From: terwer Date: Fri, 14 Apr 2023 21:26:34 +0800 Subject: [PATCH] feat: esbuild inject env --- apps/zhi-core/babel.config.cjs | 30 +++++++++ apps/zhi-core/env.d.ts | 28 ++++++++ apps/zhi-core/esbuild.config.ts | 2 +- apps/zhi-core/src/index.ts | 3 +- apps/zhi-env/.env.development | 1 + apps/zhi-env/.env.development.example | 1 + apps/zhi-env/.env.production | 1 + apps/zhi-env/.env.production.example | 1 + apps/zhi-env/.env.test | 1 + apps/zhi-env/.env.test.example | 1 + apps/zhi-env/README.md | 24 ++++--- apps/zhi-env/esbuild.config.ts | 8 ++- apps/zhi-env/package.json | 15 +++-- apps/zhi-env/scripts/build.ts | 11 ++- apps/zhi-env/scripts/utils.ts | 71 ++++++++++++++++++++ apps/zhi-env/src/index.spec.ts | 15 +++-- apps/zhi-env/src/index.ts | 5 ++ apps/zhi-env/src/lib/EnvConstants.ts | 5 ++ apps/zhi-env/src/lib/zhi-env.ts | 2 +- packages/jest-config-custom/babel.config.cjs | 3 +- packages/jest-config-custom/package.json | 2 +- pnpm-lock.yaml | 39 ++++++++++- 22 files changed, 234 insertions(+), 35 deletions(-) create mode 100644 apps/zhi-core/babel.config.cjs create mode 100644 apps/zhi-core/env.d.ts create mode 100644 apps/zhi-env/.env.development create mode 100644 apps/zhi-env/.env.development.example create mode 100644 apps/zhi-env/.env.production create mode 100644 apps/zhi-env/.env.production.example create mode 100644 apps/zhi-env/.env.test create mode 100644 apps/zhi-env/.env.test.example create mode 100644 apps/zhi-env/scripts/utils.ts diff --git a/apps/zhi-core/babel.config.cjs b/apps/zhi-core/babel.config.cjs new file mode 100644 index 00000000..36012d6d --- /dev/null +++ b/apps/zhi-core/babel.config.cjs @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +const sharedConfig = require("jest-config-custom/babel.config.cjs") + +module.exports = { + ...sharedConfig, +} diff --git a/apps/zhi-core/env.d.ts b/apps/zhi-core/env.d.ts new file mode 100644 index 00000000..244ec48c --- /dev/null +++ b/apps/zhi-core/env.d.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/apps/zhi-core/esbuild.config.ts b/apps/zhi-core/esbuild.config.ts index f533ec7d..de039db8 100644 --- a/apps/zhi-core/esbuild.config.ts +++ b/apps/zhi-core/esbuild.config.ts @@ -43,7 +43,7 @@ export const esbuildConfig: BuildOptions = { entryPoints: ["src/index.ts"], outfile: path.join(outDir, "theme.js"), bundle: true, - format: "cjs", + format: "esm", platform: "node", plugins: [ dtsPlugin(), diff --git a/apps/zhi-core/src/index.ts b/apps/zhi-core/src/index.ts index 02490670..039c0943 100644 --- a/apps/zhi-core/src/index.ts +++ b/apps/zhi-core/src/index.ts @@ -41,7 +41,8 @@ import "./style/index.styl" // const common = ZhiUtil.zhiCommon() const zhi = new Zhi() - console.log("hello, zhi theme2345", zhi) + // console.log(import.meta.env) + console.log("hello, zhi theme", zhi) // const zhi = new Zhi(common.deviceUtil.getDevice()) // await zhi.init() })() diff --git a/apps/zhi-env/.env.development b/apps/zhi-env/.env.development new file mode 100644 index 00000000..42c92bd3 --- /dev/null +++ b/apps/zhi-env/.env.development @@ -0,0 +1 @@ +VITE_DEBUG_MODE=true \ No newline at end of file diff --git a/apps/zhi-env/.env.development.example b/apps/zhi-env/.env.development.example new file mode 100644 index 00000000..42c92bd3 --- /dev/null +++ b/apps/zhi-env/.env.development.example @@ -0,0 +1 @@ +VITE_DEBUG_MODE=true \ No newline at end of file diff --git a/apps/zhi-env/.env.production b/apps/zhi-env/.env.production new file mode 100644 index 00000000..303ce5b0 --- /dev/null +++ b/apps/zhi-env/.env.production @@ -0,0 +1 @@ +VITE_DEBUG_MODE=false \ No newline at end of file diff --git a/apps/zhi-env/.env.production.example b/apps/zhi-env/.env.production.example new file mode 100644 index 00000000..303ce5b0 --- /dev/null +++ b/apps/zhi-env/.env.production.example @@ -0,0 +1 @@ +VITE_DEBUG_MODE=false \ No newline at end of file diff --git a/apps/zhi-env/.env.test b/apps/zhi-env/.env.test new file mode 100644 index 00000000..42c92bd3 --- /dev/null +++ b/apps/zhi-env/.env.test @@ -0,0 +1 @@ +VITE_DEBUG_MODE=true \ No newline at end of file diff --git a/apps/zhi-env/.env.test.example b/apps/zhi-env/.env.test.example new file mode 100644 index 00000000..42c92bd3 --- /dev/null +++ b/apps/zhi-env/.env.test.example @@ -0,0 +1 @@ +VITE_DEBUG_MODE=true \ No newline at end of file diff --git a/apps/zhi-env/README.md b/apps/zhi-env/README.md index ea79e885..5bd907fb 100644 --- a/apps/zhi-env/README.md +++ b/apps/zhi-env/README.md @@ -46,17 +46,21 @@ import Env from "zhi-env" // https://github.com/vitejs/vite/issues/9539#issuecomment-1206301266 // 1 add modules:esnext to tsconfig.json // 2 add env.d.ts -const envMeta = import.meta.env - -const customEnv = { -[EnvConstants.NODE_ENV_KEY]: EnvConstants.NODE_ENV_DEVELOPMENT, -[EnvConstants.VITE_DEBUG_MODE_KEY]: false, -// [LogConstants.LOG_LEVEL_KEY]: LogLevelEnum.LOG_LEVEL_DEBUG, -// [LogConstants.LOG_PREFIX_KEY]: "zhi-common", -...envMeta, -} +// ``` +// interface ImportMeta { +// readonly env: ImportMetaEnv +// } +// ``` +// 3 add define to esbuild, vite etc. +// ``` +// "import.meta.env": JSON.stringify({ +// NODE_ENV: isWatch ? "development" : "production", +// ...getNormalizedEnvDefines(["NODE", "VITE_"]), +// }) +// ``` -const env = new Env(customEnv) +const envMeta = import.meta.env +const env = new Env(import.meta.env) const val = env.getEnv("some-key") console.log("val=>", val) diff --git a/apps/zhi-env/esbuild.config.ts b/apps/zhi-env/esbuild.config.ts index e5d2fef4..edf36d0e 100644 --- a/apps/zhi-env/esbuild.config.ts +++ b/apps/zhi-env/esbuild.config.ts @@ -40,14 +40,16 @@ const outDir = path.join(baseDir, "dist") // const baseDir = isWatch ? "my-custom-absolute-path" : "./" // const outDir = isWatch ? baseDir : path.join(baseDir, "dist") +// console.log(process.env.VITE_DEBUG_MODE) + /** * 构建配置 */ export const esbuildConfig: BuildOptions = { entryPoints: ["src/index.ts"], - outfile: path.join(outDir, "theme.js"), + outfile: path.join(outDir, "index.js"), bundle: true, - format: "cjs", + format: "esm", platform: "node", plugins: [ dtsPlugin(), @@ -71,4 +73,4 @@ export const esbuildConfig: BuildOptions = { // watch: true, // }), ], -} \ No newline at end of file +} diff --git a/apps/zhi-env/package.json b/apps/zhi-env/package.json index 30e40280..b127d949 100644 --- a/apps/zhi-env/package.json +++ b/apps/zhi-env/package.json @@ -11,8 +11,8 @@ "license": "GPL", "keywords": [], "scripts": { - "dev": "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/build.ts --watch", - "build": "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/build.ts --production", + "dev": "ts-node -T --esm --experimental-specifier-resolution=node scripts/build.ts --watch", + "build": "ts-node -T --esm --experimental-specifier-resolution=node scripts/build.ts --production", "test": "jest", "lint": "eslint \"src/**/*.{ts,js}\" --fix", "doc": "../../packages/api-docs/node_modules/.bin/api-extractor run --local --verbose", @@ -23,14 +23,15 @@ "devDependencies": { "@types/minimist": "^1.2.2", "@types/node": "^18.15.11", + "api-docs": "workspace:*", + "dotenv": "^16.0.3", "esbuild": "^0.16.9", - "eslint-config-custom": "workspace:*", - "esbuild-plugin-d.ts": "^1.1.0", "esbuild-plugin-copy": "^2.1.1", + "esbuild-plugin-d.ts": "^1.1.0", + "eslint-config-custom": "workspace:*", + "jest-config-custom": "workspace:*", "minimist": "^1.2.8", "ts-node": "^10.9.1", - "tsconfig": "workspace:*", - "api-docs": "workspace:*", - "jest-config-custom": "workspace:*" + "tsconfig": "workspace:*" } } \ No newline at end of file diff --git a/apps/zhi-env/scripts/build.ts b/apps/zhi-env/scripts/build.ts index 9129f025..1126be2a 100644 --- a/apps/zhi-env/scripts/build.ts +++ b/apps/zhi-env/scripts/build.ts @@ -26,6 +26,7 @@ import esbuild from "esbuild" import { esbuildConfig } from "../esbuild.config" import minimist from "minimist" +import { getNormalizedEnvDefines } from "./utils" /** * zhi 主题构建 @@ -87,10 +88,16 @@ class ZhiBuild { if (!esbuildConfig.define) { esbuildConfig.define = {} } - esbuildConfig.define = { + const defineEnv = { ...esbuildConfig.define, - "process.env.NODE_ENV": isProduction ? '"production"' : '"development"', + ...import.meta.env, + "import.meta.env": JSON.stringify({ + NODE_ENV: isWatch ? "development" : "production", + ...getNormalizedEnvDefines(["NODE", "VITE_"]), + }), } + console.log("Detected env=>", defineEnv) + esbuildConfig.define = defineEnv // hande result const resultHandler = async (result: any) => { diff --git a/apps/zhi-env/scripts/utils.ts b/apps/zhi-env/scripts/utils.ts new file mode 100644 index 00000000..113cad19 --- /dev/null +++ b/apps/zhi-env/scripts/utils.ts @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import dotenv from "dotenv" + +const loadDotenv = () => { + // try to use dotenv to load in custom local env vars to existing node runtime env vars: + // eslint-disable-next-line turbo/no-undeclared-env-vars + const envFile = process.env.NODE_ENV ? `.env.${process.env.NODE_ENV}` : ".env.production" + console.log(`loading env variables from ${envFile}`) + dotenv.config({ path: envFile }) +} + +/** + * 获取环境变量,仅构建工具使用 + * + * @author terwer + * @version 0.1.0 + * @since 0.1.0 + */ +export const getNormalizedEnvDefines = (prefixes?: string[]): any => { + // load dotenv + loadDotenv() + + // collect env + const envs = { + ...import.meta.env, + } as any + for (let k in process.env) { + k = k.replace(/ /g, "") // hack for now. + + // Bypass Windows errors + if (k === "CommonProgramFiles(x86)" || k === "ProgramFiles(x86)") { + continue + } + + if (k.includes("NODE_PATH")) { + continue + } + + if (prefixes && !prefixes.some((prefix) => k.startsWith(prefix))) { + continue + } + + envs[`${k}`] = `${process.env[k]}` + } + + return envs +} diff --git a/apps/zhi-env/src/index.spec.ts b/apps/zhi-env/src/index.spec.ts index 16777530..c2fc5ec2 100644 --- a/apps/zhi-env/src/index.spec.ts +++ b/apps/zhi-env/src/index.spec.ts @@ -25,9 +25,16 @@ import { describe, expect, it } from "@jest/globals" import Env, { EnvConstants } from "./index" +import { getNormalizedEnvDefines } from "../scripts/utils" describe("zhiEnv", () => { const NOT_EXIST_KEY = "NOT_EXIST_KEY" + const defineEnv = getNormalizedEnvDefines() + + it("test node env", () => { + const nodeEnv = import.meta.env.NODE_ENV + expect(nodeEnv).toEqual(EnvConstants.NODE_ENV_TEST) + }) it("test env", () => { const env = new Env(import.meta.env) @@ -60,7 +67,7 @@ describe("zhiEnv", () => { const val = env.getStringEnv(EnvConstants.VITE_DEBUG_MODE_KEY) console.log("val=>", val) - expect(val).toBeInstanceOf("string") + expect(typeof val).toBe("string") }) it("test getBooleanEnv", function () { @@ -68,7 +75,7 @@ describe("zhiEnv", () => { const val = env.getBooleanEnv(EnvConstants.VITE_DEBUG_MODE_KEY) console.log("val=>", val) - expect(val).toBeInstanceOf("boolean") + expect(typeof val).toBe("boolean") }) it("test getEnvOrDefault", function () { @@ -76,7 +83,7 @@ describe("zhiEnv", () => { const val = env.getEnvOrDefault(NOT_EXIST_KEY, "hello") console.log("val=>", val) - expect(val).toBeInstanceOf("string") + expect(typeof val).toBe("string") }) it("test custom env", function () { @@ -86,6 +93,6 @@ describe("zhiEnv", () => { const val = env.getEnv("mykey-a") console.log("val=>", val) - expect(val).toBeInstanceOf("string") + expect(typeof val).toBe("string") }) }) diff --git a/apps/zhi-env/src/index.ts b/apps/zhi-env/src/index.ts index b5121f44..f5831c7f 100644 --- a/apps/zhi-env/src/index.ts +++ b/apps/zhi-env/src/index.ts @@ -25,5 +25,10 @@ import EnvConstants from "./lib/EnvConstants" import Env from "./lib/zhi-env" + +console.log(import.meta.env) +const env = new Env(import.meta.env) +console.log(env.getEnv(EnvConstants.VITE_DEBUG_MODE_KEY)) + export default Env export { EnvConstants } diff --git a/apps/zhi-env/src/lib/EnvConstants.ts b/apps/zhi-env/src/lib/EnvConstants.ts index a061b70a..0eb69d55 100644 --- a/apps/zhi-env/src/lib/EnvConstants.ts +++ b/apps/zhi-env/src/lib/EnvConstants.ts @@ -46,6 +46,11 @@ class EnvConstants { */ public static NODE_ENV_PRODUCTION = "production" + /** + * 测试环境 + */ + public static NODE_ENV_TEST = "test" + /** * 是否处于调试模式 */ diff --git a/apps/zhi-env/src/lib/zhi-env.ts b/apps/zhi-env/src/lib/zhi-env.ts index 5718e2db..13ae0563 100644 --- a/apps/zhi-env/src/lib/zhi-env.ts +++ b/apps/zhi-env/src/lib/zhi-env.ts @@ -70,7 +70,7 @@ class Env { env = this.envMeta[key] } } catch (e: any) { - console.error(e) + // console.error(e) } return env diff --git a/packages/jest-config-custom/babel.config.cjs b/packages/jest-config-custom/babel.config.cjs index 25f4ffa3..e274bbe5 100644 --- a/packages/jest-config-custom/babel.config.cjs +++ b/packages/jest-config-custom/babel.config.cjs @@ -24,6 +24,5 @@ */ module.exports = { - presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript"], - plugins: ["babel-plugin-transform-vite-meta-env"], + presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript","babel-preset-vite"], } diff --git a/packages/jest-config-custom/package.json b/packages/jest-config-custom/package.json index f7c112d1..85d51ca4 100644 --- a/packages/jest-config-custom/package.json +++ b/packages/jest-config-custom/package.json @@ -15,7 +15,7 @@ "@babel/preset-typescript": "^7.21.4", "@types/jest": "^29.5.0", "babel-jest": "^29.5.0", - "babel-plugin-transform-vite-meta-env": "^1.0.3", + "babel-preset-vite": "^1.1.0", "jest": "^29.5.0", "typescript": "^4.7.4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 885ee71e..395e4ad6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -131,6 +131,9 @@ importers: api-docs: specifier: workspace:* version: link:../../packages/api-docs + dotenv: + specifier: ^16.0.3 + version: 16.0.3 esbuild: specifier: ^0.16.9 version: 0.16.9 @@ -219,9 +222,9 @@ importers: babel-jest: specifier: ^29.5.0 version: 29.5.0(@babel/core@7.21.4) - babel-plugin-transform-vite-meta-env: - specifier: ^1.0.3 - version: 1.0.3 + babel-preset-vite: + specifier: ^1.1.0 + version: 1.1.0 jest: specifier: ^29.5.0 version: 29.5.0 @@ -4150,6 +4153,21 @@ packages: '@types/babel__core': 7.20.0 dev: true + /babel-plugin-transform-vite-meta-glob@1.0.3: + resolution: {integrity: sha512-JW3VnwUjJqpj0FM0vJFxrGdxSBcHOa0j5YMvvtXYPmFshroq53nbK9dqRETgjXlMrfIz0oU/6ki+u1GdVWdNHA==} + dependencies: + '@babel/runtime': 7.21.0 + '@types/babel__core': 7.20.0 + glob: 7.2.3 + dev: true + + /babel-plugin-transform-vite-meta-hot@1.0.0: + resolution: {integrity: sha512-qF7T46bDG5UPPOfy4MFgQJyd3mZvm1sGOR2gZ4lIHy6DEcxAVTIt39/adAn89il44CvwestshuEybKPMR+L/Tg==} + dependencies: + '@babel/runtime': 7.21.0 + '@types/babel__core': 7.20.0 + dev: true + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.21.4): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: @@ -4181,6 +4199,16 @@ packages: babel-preset-current-node-syntax: 1.0.1(@babel/core@7.21.4) dev: true + /babel-preset-vite@1.1.0: + resolution: {integrity: sha512-5OnV5RPD+Byi1KnhQpgzz2e1Bc2PFJ9i6wy1VDMPmYu0NjaxcyJuWy9piBoefCL4tMn1nm3VtvInPNitCHJnbQ==} + dependencies: + '@babel/runtime': 7.21.0 + '@types/babel__core': 7.20.0 + babel-plugin-transform-vite-meta-env: 1.0.3 + babel-plugin-transform-vite-meta-glob: 1.0.3 + babel-plugin-transform-vite-meta-hot: 1.0.0 + dev: true + /bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} dev: false @@ -5096,6 +5124,11 @@ packages: domhandler: 5.0.3 dev: true + /dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + dev: true + /dset@3.1.2: resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} engines: {node: '>=4'}