-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathvite.config.mjs
More file actions
173 lines (168 loc) · 5.58 KB
/
vite.config.mjs
File metadata and controls
173 lines (168 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import { defineConfig, loadEnv } from 'vite';
import path from 'path';
import { fileURLToPath } from 'url';
import { createHtmlPlugin } from 'vite-plugin-html';
import { visualizer } from 'rollup-plugin-visualizer';
import { getAllCdnUrls, getExternals, getGlobals } from './cdn.config.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const isProduction = mode === 'production';
// CDN 配置
const useCdn = env.VITE_USE_CDN === 'true';
const cdnProvider = env.VITE_CDN_PROVIDER || 'npmmirror';
const cdnData = useCdn ? getAllCdnUrls(cdnProvider) : { js: [], css: [] };
// Rollup 外部依赖配置 (如果启用 CDN)
const externalDeps = useCdn ? getExternals() : [];
const globals = useCdn ? getGlobals() : {};
return {
root: 'src',
base: './',
plugins: [
createHtmlPlugin({
minify: isProduction,
inject: {
data: {
title: 'API Monitor',
// 注入 CDN 资源
cdnScriptTags: cdnData.js
.map(item => `<script src="${item.url}" defer crossorigin="anonymous"></script>`)
.join('\n '),
cdnStyleTags: cdnData.css
.map(
url =>
`<link rel="stylesheet" href="${url}" media="print" onload="this.media='all'; this.onload=null;">`
)
.join('\n '),
},
},
}),
// 构建分析插件 (输出到 dist/stats.html)
visualizer({
filename: 'dist/stats.html',
open: false,
gzipSize: true,
brotliSize: true,
}),
],
build: {
outDir: '../dist',
assetsDir: 'assets',
emptyOutDir: true,
sourcemap: !isProduction,
minify: isProduction ? 'terser' : false,
rollupOptions: {
external: externalDeps,
output: {
globals: globals,
// 代码分割策略
manualChunks: id => {
// 注意:已经在 externalDeps 中的包(CDN 引用的包)不能在此处分包
if (id.includes('node_modules')) {
// 终端组件
if (id.includes('@xterm')) {
return 'vendor-xterm';
}
// 播放器与多媒体
if (
id.includes('artplayer') ||
id.includes('flv.js') ||
id.includes('hls.js') ||
id.includes('plyr')
) {
return 'vendor-media';
}
// Pixi 渲染引擎
if (id.includes('@pixi') || id.includes('pixi-filters')) {
return 'vendor-pixi';
}
// 其他大型工具库 (且不在 CDN 中的)
if (
id.includes('axios') ||
id.includes('marked') ||
id.includes('dompurify') ||
id.includes('uuid') ||
id.includes('vue')
) {
// 如果启用了 CDN 且 vue/axios 在 external 中,Vite 会自动忽略它们
// 这里我们显式将非 CDN 的大库打包
return 'vendor-utils';
}
}
},
},
},
terserOptions: {
compress: {
drop_console: false, // 暂时禁用,确保调试信息可见
drop_debugger: isProduction,
pure_funcs: [], // 不要优化掉任何函数调用
},
mangle: {
reserved: ['compile', 'compileToFunction', 'baseCompile'], // 保留编译器函数名
},
},
},
// 强制预构建 Vue 编译器
optimizeDeps: {
include: ['vue', '@vue/compiler-dom', '@vue/compiler-core'],
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
// 关键:确保支持在 HTML 中直接写模板 (Runtime Compilation)
// 必须使用 esm-bundler 版本,它会自动引入 @vue/compiler-dom
// esm-browser 版本不包含编译器,会导致 compiler-30 错误
vue: 'vue/dist/vue.esm-bundler.js',
},
},
define: {
__USE_CDN__: JSON.stringify(useCdn),
__CDN_PROVIDER__: JSON.stringify(cdnProvider),
// Vue 特性标志,消除控制台警告
__VUE_OPTIONS_API__: JSON.stringify(true),
__VUE_PROD_DEVTOOLS__: JSON.stringify(false),
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(false),
},
server: {
host: true, // 监听所有网络接口,允许手机访问
port: 5173,
hmr: {
protocol: 'ws',
host: 'localhost',
port: 5173,
},
// SPA 历史回退:所有非静态资源路由都返回 index.html
historyApiFallback: {
rewrites: [
{ from: /^\/api\/.*$/, to: '/index.html' }, // 仅做兜底,实际应由 proxy 处理
],
disableDotRule: true, // 允许路径中带点
},
proxy: {
'/api': {
target: `http://127.0.0.1:${env.PORT || 3000}`,
changeOrigin: true,
},
'/v1': {
target: `http://127.0.0.1:${env.PORT || 3000}`,
changeOrigin: true,
},
'/socket.io': {
target: `http://127.0.0.1:${env.PORT || 3000}`,
ws: true,
},
'/ws': {
target: `http://127.0.0.1:${env.PORT || 3000}`,
ws: true,
changeOrigin: true,
},
'/uploads': {
target: `http://127.0.0.1:${env.PORT || 3000}`,
changeOrigin: true,
},
},
},
};
});