fix: 官网静态资源改发布到 /site/assets,修复线上 404

postbuild 不再合并到 dist/assets(与 Vite 产物冲突且 Windows 下 cpSync 失败),改为完整复制 IDE官网 到 dist/site 并注入 base href;nginx 增加 /site/ 静态路由。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-08-24 19:44:31 +08:00
parent 70d59a0ea9
commit 7c08e83f38
4 changed files with 54 additions and 11 deletions

View File

@ -5,7 +5,7 @@
(function (global) { (function (global) {
'use strict'; 'use strict';
const WORLD_URL = '/assets/data/world-110m.json'; const WORLD_URL = 'assets/data/world-110m.json';
const HUB = [114.06, 22.55]; const HUB = [114.06, 22.55];
const LABELS = { const LABELS = {

View File

@ -55,6 +55,14 @@ server {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Cache-Control "no-cache, no-store, must-revalidate";
} }
# 官网静态资源(/site/index.html 通过 base href 引用 /site/assets/...)
location ^~ /site/ {
try_files $uri =404;
expires 7d;
add_header Cache-Control "public";
access_log off;
}
# ============ 客户 / 管理端登录入口 ============ # ============ 客户 / 管理端登录入口 ============
location = /login { location = /login {
try_files /index.html =200; try_files /index.html =200;

View File

@ -22,6 +22,13 @@ server {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Cache-Control "no-cache, no-store, must-revalidate";
} }
location ^~ /site/ {
try_files $uri =404;
expires 7d;
add_header Cache-Control "public";
access_log off;
}
location = /login { location = /login {
try_files /index.html =200; try_files /index.html =200;
} }

View File

@ -6,6 +6,30 @@ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const dist = path.join(root, 'dist'); const dist = path.join(root, 'dist');
const siteSrc = path.join(root, 'IDE官网'); const siteSrc = path.join(root, 'IDE官网');
const legacyLoginDir = path.join(dist, 'login'); const legacyLoginDir = path.join(dist, 'login');
const siteDir = path.join(dist, 'site');
/** Avoid fs.cpSync merge into dist/assets (conflicts with Vite + can crash on Windows). */
function copyDirSync(src, dest, options = {}) {
const { skipDirNames = new Set() } = options;
fs.mkdirSync(dest, { recursive: true });
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
if (entry.isDirectory() && skipDirNames.has(entry.name)) continue;
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
copyDirSync(srcPath, destPath, options);
continue;
}
if (entry.isFile()) {
fs.copyFileSync(srcPath, destPath);
}
}
}
function injectSiteBaseHref(html) {
if (html.includes('<base ')) return html;
return html.replace('<head>', '<head>\n <base href="/site/">');
}
if (fs.existsSync(legacyLoginDir)) { if (fs.existsSync(legacyLoginDir)) {
fs.rmSync(legacyLoginDir, { recursive: true, force: true }); fs.rmSync(legacyLoginDir, { recursive: true, force: true });
@ -17,22 +41,26 @@ function copyOfficialSite() {
return; return;
} }
const siteDir = path.join(dist, 'site'); if (fs.existsSync(siteDir)) {
fs.mkdirSync(siteDir, { recursive: true }); fs.rmSync(siteDir, { recursive: true, force: true });
fs.copyFileSync(path.join(siteSrc, 'index.html'), path.join(siteDir, 'index.html')); }
copyDirSync(siteSrc, siteDir, {
skipDirNames: new Set(['.well-known']),
});
const siteIndex = path.join(siteDir, 'index.html');
if (fs.existsSync(siteIndex)) {
const html = fs.readFileSync(siteIndex, 'utf8');
fs.writeFileSync(siteIndex, injectSiteBaseHref(html), 'utf8');
}
const src9610 = path.join(siteSrc, '9610.html'); const src9610 = path.join(siteSrc, '9610.html');
if (fs.existsSync(src9610)) { if (fs.existsSync(src9610)) {
fs.copyFileSync(src9610, path.join(dist, '9610.html')); fs.copyFileSync(src9610, path.join(dist, '9610.html'));
} }
const srcAssets = path.join(siteSrc, 'assets'); console.log('[postbuild] copied official site to dist/site (assets under /site/assets)');
const destAssets = path.join(dist, 'assets');
if (fs.existsSync(srcAssets)) {
fs.cpSync(srcAssets, destAssets, { recursive: true });
}
console.log('[postbuild] copied official site to dist/site + 9610.html + assets');
} }
copyOfficialSite(); copyOfficialSite();