ALIEZ 1 неделя назад
Родитель
Сommit
c44c1147b6
3 измененных файлов с 47 добавлено и 2 удалено
  1. 2 1
      ecosystem.config.cjs
  2. 1 1
      package.json
  3. 44 0
      scripts/build-with-env.mjs

+ 2 - 1
ecosystem.config.cjs

@@ -8,7 +8,8 @@ const path = require("path");
  * 敏感信息不要写进本文件,用 PM2 --env 或服务器环境变量注入。
  *
  * NEXT_PUBLIC_*(如 API 地址)在 next build 时已打入前端包;PM2 里再改不会更新浏览器里的接口域名。
- * 测试 / 生产请分别用 npm run build:test 与 npm run build,或在构建前注入相同的环境变量。
+ * 测试 / 生产请分别用 npm run build:test 与 npm run build。
+ * build:test 读取 .env.development(含 API_PROXY_TARGET 等),再执行 next build。
  *
  * 若 API 使用 __ORIGIN__(与站点同源),服务端渲染发请求时还需在构建或运行环境提供
  * NEXT_PUBLIC_SITE_URL(例如 https://你的前端域名),否则服务端拿不到页面域名。

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
     "dev:reset": "sh -c 'PIDS=$(lsof -ti tcp:3000 -sTCP:LISTEN); if [ -n \"$PIDS\" ]; then echo \"Killing port 3000 process: $PIDS\"; kill $PIDS; fi; rm -f .next/dev/lock; npm run dev'",
     "dev:restart": "npm run dev:clean",
     "build": "next build",
-    "build:test": "cross-env NEXT_PUBLIC_APP_ENV=test next build",
+    "build:test": "node ./scripts/build-with-env.mjs .env.development",
     "start": "next start",
     "lint": "eslint",
     "pm2:test": "pm2 start ecosystem.config.cjs --only jchl-test",

+ 44 - 0
scripts/build-with-env.mjs

@@ -0,0 +1,44 @@
+#!/usr/bin/env node
+/**
+ * 用指定 env 文件注入 process.env 后执行 next build。
+ * 已注入的变量优先于 .env.production(Next 不会覆盖已有 process.env)。
+ */
+import { readFileSync, existsSync } from "fs";
+import { spawnSync } from "child_process";
+import { resolve, dirname } from "path";
+import { fileURLToPath } from "url";
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const root = resolve(__dirname, "..");
+const envFile = process.argv[2] || ".env.development";
+const envPath = resolve(root, envFile);
+
+if (!existsSync(envPath)) {
+  console.error(`[build-with-env] 找不到 ${envPath}`);
+  process.exit(1);
+}
+
+const env = { ...process.env, NODE_ENV: "production" };
+
+for (const line of readFileSync(envPath, "utf8").split("\n")) {
+  const trimmed = line.trim();
+  if (!trimmed || trimmed.startsWith("#")) continue;
+  const eq = trimmed.indexOf("=");
+  if (eq === -1) continue;
+  const key = trimmed.slice(0, eq).trim();
+  let val = trimmed.slice(eq + 1).trim();
+  if (
+    (val.startsWith('"') && val.endsWith('"')) ||
+    (val.startsWith("'") && val.endsWith("'"))
+  ) {
+    val = val.slice(1, -1);
+  }
+  env[key] = val;
+}
+
+console.log(
+  `[build-with-env] ${envFile} → NEXT_PUBLIC_APP_ENV=${env.NEXT_PUBLIC_APP_ENV}, API_PROXY_TARGET=${env.API_PROXY_TARGET}`,
+);
+
+const r = spawnSync("next", ["build"], { cwd: root, env, stdio: "inherit" });
+process.exit(r.status ?? 1);