104 lines
3.7 KiB
TypeScript
104 lines
3.7 KiB
TypeScript
import { existsSync } from "node:fs";
|
||
import path from "node:path";
|
||
import { fileURLToPath } from "node:url";
|
||
|
||
import react from "@vitejs/plugin-react";
|
||
import { defineConfig, type Plugin } from "vite";
|
||
import sourceIdentifierPlugin from "vite-plugin-source-identifier";
|
||
|
||
const rootDir = fileURLToPath(new URL(".", import.meta.url));
|
||
|
||
// 依赖预构建缓存被重建后(pnpm install / 重复启动 vite / --force),
|
||
// 残留的旧浏览器标签页仍会按旧版本号(?v=<hash>)请求已删除的 chunk,
|
||
// 每次都在终端刷 "The file does not exist ... in the optimize deps directory"。
|
||
// 该插件拦截这类「文件确实不存在」的 deps 请求,返回一段触发 location.reload()
|
||
// 的模块脚本,让旧页面自愈到新版本;sessionStorage 防止真正的坏页面无限刷新。
|
||
const staleDepsChunkSelfReload = (): Plugin => ({
|
||
name: "stale-deps-chunk-self-reload",
|
||
configureServer(server) {
|
||
const depsDir = path.join(rootDir, "node_modules", ".vite", "deps");
|
||
server.middlewares.use((req, res, next) => {
|
||
const match = /^\/node_modules\/\.vite\/deps\/([^?]+)/.exec(req.url ?? "");
|
||
if (!match) {
|
||
next();
|
||
return;
|
||
}
|
||
const filePath = path.join(depsDir, decodeURIComponent(match[1]));
|
||
if (existsSync(filePath)) {
|
||
next();
|
||
return;
|
||
}
|
||
res.setHeader("Content-Type", "application/javascript");
|
||
res.end(
|
||
"if(!sessionStorage.getItem('__vite_stale_chunk_reloaded__')){" +
|
||
"sessionStorage.setItem('__vite_stale_chunk_reloaded__','1');" +
|
||
"location.reload();}",
|
||
);
|
||
});
|
||
},
|
||
});
|
||
// Tailwind 4 emits CSS cascade layers, which require Chrome 99+. Chrome 100
|
||
// is therefore the practical lower bound for this Win7 legacy build.
|
||
const LEGACY_CHROME = 100 << 16;
|
||
|
||
export default defineConfig({
|
||
plugins: [staleDepsChunkSelfReload(), sourceIdentifierPlugin(), react()],
|
||
css: {
|
||
// Also used by the production CSS minifier. Development CSS is handled
|
||
// by the matching PostCSS compatibility pass in postcss.config.js.
|
||
lightningcss: {
|
||
targets: {
|
||
chrome: LEGACY_CHROME,
|
||
},
|
||
},
|
||
},
|
||
resolve: {
|
||
alias: [
|
||
{
|
||
// react-syntax-highlighter@16.1.1 exposes an async `sqlMore`
|
||
// loader, but its own highlight.js@10.x dependency has no
|
||
// `sql_more` module. Reuse the bundled SQL grammar so Rollup can
|
||
// resolve every generated language loader without leaving a broken
|
||
// browser-time external import.
|
||
find: /^highlight\.js\/lib\/languages\/sql_more$/,
|
||
replacement: "highlight.js/lib/languages/sql",
|
||
},
|
||
{
|
||
find: "@/env",
|
||
replacement: path.resolve(rootDir, "src/env.ts"),
|
||
},
|
||
{
|
||
find: "next/navigation",
|
||
replacement: path.resolve(rootDir, "src/shims/next-navigation.ts"),
|
||
},
|
||
{
|
||
find: "next/link",
|
||
replacement: path.resolve(rootDir, "src/shims/next-link.tsx"),
|
||
},
|
||
{
|
||
find: "@vite",
|
||
replacement: path.resolve(rootDir, "src"),
|
||
},
|
||
{
|
||
find: "@",
|
||
replacement: path.resolve(rootDir, "src"),
|
||
},
|
||
],
|
||
},
|
||
// Keep the current portable-file default, while allowing container builds to
|
||
// emit absolute asset URLs. The latter is required for BrowserRouter pages
|
||
// behind Nginx: a request to /page/... must still load /assets/... rather
|
||
// than /page/assets/....
|
||
base: process.env.VITE_ASSET_BASE ?? "./",
|
||
build: {
|
||
cssMinify: "lightningcss",
|
||
target: "chrome100",
|
||
},
|
||
server: {
|
||
// 与 scripts/env.sh FRONTEND_PORT=5174、圆桌 wujie 嵌入文档一致。
|
||
port: 5173,
|
||
// 无界宿主跨域 fetch 子应用静态资源时,Vite 需回显请求的 Origin。
|
||
cors: true,
|
||
},
|
||
});
|