Переглянути джерело

fix: preview base path via VITE_BASE env var

- vite.config.js reads process.env.VITE_BASE for dev server base path
- previewService passes VITE_BASE instead of generating temp config file
- nginx proxy_pass must NOT have trailing slash to preserve /ads-preview/ prefix
guoziyun 3 тижнів тому
батько
коміт
91c16cac56

+ 1 - 1
platform/server/dist/services/previewService.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"previewService.d.ts","sourceRoot":"","sources":["../../src/services/previewService.ts"],"names":[],"mappings":"AAoCA;;GAEG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,IAAI,CAON;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAsBlC;AAED,wBAAgB,gBAAgB,IAAI;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAMrG"}
+{"version":3,"file":"previewService.d.ts","sourceRoot":"","sources":["../../src/services/previewService.ts"],"names":[],"mappings":"AAoCA;;GAEG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,IAAI,CAON;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAgBlC;AAED,wBAAgB,gBAAgB,IAAI;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAMrG"}

+ 14 - 18
platform/server/dist/services/previewService.js

@@ -53,21 +53,20 @@ async function startPreview(creativeId, theme, storageDir) {
     const configContent = (0, configGenerator_1.generateAdConfig)({ creativeId, theme, storageDir });
     const configPath = path_1.default.join(TEMPLATE_DIR, "src", "filler", "_ad_config_.ts");
     fs_1.default.writeFileSync(configPath, configContent, "utf-8");
-    // 4. 用 vite.config.preview.js(硬编码 base 路径)覆盖默认 config
+    // 4. 通过 VITE_BASE 环境变量传入 base 路径(vite.config.js 读取)
+    //    注意:nginx 必须配合去掉 proxy_pass 尾部斜杠,保持 /ads-preview/ 前缀不变
     const previewBase = process.env.PREVIEW_BASE_PATH || "/";
-    const originalConfig = fs_1.default.readFileSync(path_1.default.join(TEMPLATE_DIR, "vite.config.js"), "utf-8");
-    // 在 return 语句前注入 base
-    const patchedConfig = originalConfig.replace("return {", `return {\n    base: "${previewBase}",`);
-    const previewConfigPath = path_1.default.join(TEMPLATE_DIR, "vite.config.preview.js");
-    fs_1.default.writeFileSync(previewConfigPath, patchedConfig, "utf-8");
     console.log(`[preview] Starting Vite dev server on port ${PREVIEW_PORT} (base: ${previewBase})...`);
     viteProcess = (0, child_process_1.spawn)(path_1.default.join(TEMPLATE_DIR, "node_modules", ".bin", "vite"), [
         "--port", String(PREVIEW_PORT),
         "--strictPort",
-        "--config", previewConfigPath,
     ], {
         cwd: TEMPLATE_DIR,
-        env: { ...process.env, AD_CONFIG_PATH: "src/filler/_ad_config_.ts" },
+        env: {
+            ...process.env,
+            AD_CONFIG_PATH: "src/filler/_ad_config_.ts",
+            VITE_BASE: previewBase,
+        },
         stdio: ["ignore", "pipe", "pipe"],
     });
     viteProcess.stdout?.on("data", (data) => {
@@ -83,11 +82,15 @@ async function startPreview(creativeId, theme, storageDir) {
     });
     currentCreativeId = creativeId;
     // 5. 等待 Vite 就绪
-    const localUrl = `http://localhost:${PREVIEW_PORT}`;
-    console.log("[preview] Waiting for Vite to be ready...");
-    await waitForReady(localUrl);
+    //    Vite 有 base 路径时,根路径可能 404,需要用带 prefix 的 URL 检查
+    const checkUrl = previewBase !== "/"
+        ? `http://localhost:${PREVIEW_PORT}${previewBase}`
+        : `http://localhost:${PREVIEW_PORT}`;
+    console.log(`[preview] Waiting for Vite to be ready (checking ${checkUrl})...`);
+    await waitForReady(checkUrl);
     console.log("[preview] Vite is ready.");
     // 生产环境通过 nginx 代理暴露公网 URL,本地开发直接用 localhost
+    const localUrl = `http://localhost:${PREVIEW_PORT}`;
     const publicUrl = process.env.PREVIEW_PUBLIC_URL || localUrl;
     return { url: publicUrl };
 }
@@ -117,13 +120,6 @@ function stopPreview() {
         viteProcess = null;
     }
     currentCreativeId = null;
-    // 清理临时 vite config
-    try {
-        const previewConfigPath = path_1.default.join(TEMPLATE_DIR, "vite.config.preview.js");
-        if (fs_1.default.existsSync(previewConfigPath))
-            fs_1.default.unlinkSync(previewConfigPath);
-    }
-    catch { }
     // 确保端口释放
     try {
         (0, child_process_2.execSync)(`lsof -ti :${PREVIEW_PORT} | xargs kill -9 2>/dev/null`, { stdio: "ignore" });

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
platform/server/dist/services/previewService.js.map


+ 14 - 20
platform/server/src/services/previewService.ts

@@ -53,25 +53,21 @@ export async function startPreview(
   const configPath = path.join(TEMPLATE_DIR, "src", "filler", "_ad_config_.ts");
   fs.writeFileSync(configPath, configContent, "utf-8");
 
-  // 4. 用 vite.config.preview.js(硬编码 base 路径)覆盖默认 config
+  // 4. 通过 VITE_BASE 环境变量传入 base 路径(vite.config.js 读取)
+  //    注意:nginx 必须配合去掉 proxy_pass 尾部斜杠,保持 /ads-preview/ 前缀不变
   const previewBase = process.env.PREVIEW_BASE_PATH || "/";
-  const originalConfig = fs.readFileSync(path.join(TEMPLATE_DIR, "vite.config.js"), "utf-8");
-  // 在 return 语句前注入 base
-  const patchedConfig = originalConfig.replace(
-    "return {",
-    `return {\n    base: "${previewBase}",`
-  );
-  const previewConfigPath = path.join(TEMPLATE_DIR, "vite.config.preview.js");
-  fs.writeFileSync(previewConfigPath, patchedConfig, "utf-8");
 
   console.log(`[preview] Starting Vite dev server on port ${PREVIEW_PORT} (base: ${previewBase})...`);
   viteProcess = spawn(path.join(TEMPLATE_DIR, "node_modules", ".bin", "vite"), [
     "--port", String(PREVIEW_PORT),
     "--strictPort",
-    "--config", previewConfigPath,
   ], {
     cwd: TEMPLATE_DIR,
-    env: { ...process.env, AD_CONFIG_PATH: "src/filler/_ad_config_.ts" },
+    env: {
+      ...process.env,
+      AD_CONFIG_PATH: "src/filler/_ad_config_.ts",
+      VITE_BASE: previewBase,
+    },
     stdio: ["ignore", "pipe", "pipe"],
   });
 
@@ -90,12 +86,16 @@ export async function startPreview(
   currentCreativeId = creativeId;
 
   // 5. 等待 Vite 就绪
-  const localUrl = `http://localhost:${PREVIEW_PORT}`;
-  console.log("[preview] Waiting for Vite to be ready...");
-  await waitForReady(localUrl);
+  //    Vite 有 base 路径时,根路径可能 404,需要用带 prefix 的 URL 检查
+  const checkUrl = previewBase !== "/"
+    ? `http://localhost:${PREVIEW_PORT}${previewBase}`
+    : `http://localhost:${PREVIEW_PORT}`;
+  console.log(`[preview] Waiting for Vite to be ready (checking ${checkUrl})...`);
+  await waitForReady(checkUrl);
   console.log("[preview] Vite is ready.");
 
   // 生产环境通过 nginx 代理暴露公网 URL,本地开发直接用 localhost
+  const localUrl = `http://localhost:${PREVIEW_PORT}`;
   const publicUrl = process.env.PREVIEW_PUBLIC_URL || localUrl;
   return { url: publicUrl };
 }
@@ -131,12 +131,6 @@ export function stopPreview(): void {
   }
   currentCreativeId = null;
 
-  // 清理临时 vite config
-  try {
-    const previewConfigPath = path.join(TEMPLATE_DIR, "vite.config.preview.js");
-    if (fs.existsSync(previewConfigPath)) fs.unlinkSync(previewConfigPath);
-  } catch {}
-
   // 确保端口释放
   try {
     execSync(`lsof -ti :${PREVIEW_PORT} | xargs kill -9 2>/dev/null`, { stdio: "ignore" });

+ 2 - 0
templates/coloring/vite.config.js

@@ -43,6 +43,8 @@ module.exports = defineConfig(({ mode }) => {
   const outDir = output ? `dist/${output}` : "dist";
 
   return {
+    // VITE_BASE 由 previewService 传入,用于预览服务的子路径部署
+    base: process.env.VITE_BASE || undefined,
     plugins: [viteSingleFile(), finalizeHtmlPlugin(outDir, adapter)],
     server: {
       allowedHosts: ["color2.jccytech.cn", "localhost", ".jccytech.cn"],

Деякі файли не було показано, через те що забагато файлів було змінено