105 lines
3.2 KiB
TypeScript
105 lines
3.2 KiB
TypeScript
import { jsxLocPlugin } from "@builder.io/vite-plugin-jsx-loc";
|
|
import tailwindcss from "@tailwindcss/vite";
|
|
import react from "@vitejs/plugin-react";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { defineConfig, type Plugin } from "vite";
|
|
import { vitePluginManusRuntime } from "vite-plugin-manus-runtime";
|
|
|
|
const PROJECT_ROOT = import.meta.dirname;
|
|
|
|
/** 构建后将统一入口 i.html 复制到 dist/ 根目录 */
|
|
function vitePluginCopyRouterEntry(): Plugin {
|
|
const src = path.resolve(import.meta.dirname, "client", "i.html");
|
|
const dest = path.resolve(import.meta.dirname, "dist", "i.html");
|
|
return {
|
|
name: "copy-router-entry",
|
|
closeBundle() {
|
|
if (process.env.NODE_ENV !== "production") return;
|
|
const distRoot = path.resolve(import.meta.dirname, "dist");
|
|
if (!fs.existsSync(distRoot)) fs.mkdirSync(distRoot, { recursive: true });
|
|
fs.copyFileSync(src, dest);
|
|
},
|
|
};
|
|
}
|
|
|
|
const plugins = [
|
|
react(),
|
|
tailwindcss(),
|
|
jsxLocPlugin(),
|
|
vitePluginManusRuntime(),
|
|
vitePluginCopyRouterEntry(),
|
|
];
|
|
|
|
export default defineConfig({
|
|
plugins,
|
|
base: process.env.NODE_ENV === "production" ? "/x8/v2/modern/" : "/",
|
|
resolve: {
|
|
alias: {
|
|
"@": path.resolve(import.meta.dirname, "client", "src"),
|
|
"@shared": path.resolve(import.meta.dirname, "shared"),
|
|
"@assets": path.resolve(import.meta.dirname, "attached_assets"),
|
|
},
|
|
dedupe: ["react", "react-dom"],
|
|
},
|
|
envDir: path.resolve(import.meta.dirname),
|
|
root: path.resolve(import.meta.dirname, "client"),
|
|
publicDir: path.resolve(import.meta.dirname, "client/public"),
|
|
// 性能优化
|
|
build: {
|
|
target: 'esnext',
|
|
cssTarget: 'esnext',
|
|
outDir: path.resolve(import.meta.dirname, "dist/modern"),
|
|
emptyOutDir: true,
|
|
minify: 'terser',
|
|
terserOptions: {
|
|
compress: {
|
|
drop_console: true,
|
|
drop_debugger: true,
|
|
},
|
|
},
|
|
rollupOptions: {
|
|
input: {
|
|
i: path.resolve(import.meta.dirname, "client", "i.modern.html"),
|
|
},
|
|
output: {
|
|
manualChunks(id) {
|
|
if (!id.includes("node_modules")) return;
|
|
// Only split echarts (lazy EQ page). Do not manually chunk react, radix, lucide,
|
|
// or ai-markdown — forced splits hoist shared helpers and break React.forwardRef.
|
|
if (id.includes("/echarts/")) return "echarts-vendor";
|
|
},
|
|
},
|
|
},
|
|
// streamdown pulls full @shikijs/langs (~7 MB) + themes + mermaid; lazy-loaded with AIPage.
|
|
chunkSizeWarningLimit: 15000,
|
|
cssCodeSplit: true,
|
|
},
|
|
server: {
|
|
port: 3000,
|
|
strictPort: false, // Will find next available port if 3000 is busy
|
|
host: true,
|
|
// Browser requests with Origin are rejected (403) by the cloud API; proxy in dev avoids CORS/WAF.
|
|
proxy: {
|
|
"/luxsin-audio-api": {
|
|
target: "https://api.luxsin.com.cn",
|
|
changeOrigin: true,
|
|
rewrite: (p) => p.replace(/^\/luxsin-audio-api/, "/audio"),
|
|
},
|
|
},
|
|
allowedHosts: [
|
|
".manuspre.computer",
|
|
".manus.computer",
|
|
".manus-asia.computer",
|
|
".manuscomputer.ai",
|
|
".manusvm.computer",
|
|
"localhost",
|
|
"127.0.0.1",
|
|
],
|
|
fs: {
|
|
strict: true,
|
|
deny: ["**/.*"],
|
|
},
|
|
},
|
|
});
|