import { fileURLToPath, URL } from 'node:url' import { loadEnv, defineConfig, ConfigEnv } from 'vite' import type { UserConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueDevTools from 'vite-plugin-vue-devtools' import basicSsl from '@vitejs/plugin-basic-ssl' // 自动导入插件 import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' // Element Plus 组件自动导入 import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' // 自定义插件:修复 face-api.js 模型文件的 MIME 类型 function faceModelsMimeTypePlugin() { return { name: 'face-models-mime-type', configureServer(server) { server.middlewares.use((req, res, next) => { const url = req.url || '' if (url.includes('.shard1') || url.includes('.shard2')) { res.setHeader('Content-Type', 'application/wasm') } else if (url.includes('.weights_manifest.json')) { res.setHeader('Content-Type', 'application/json') } next() }) }, } } // https://vite.dev/config/ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { const isProduction = mode === 'production' const env = loadEnv(mode, process.cwd()) return { // 解决 face-api.js 模型文件 MIME 类型问题 assetsInclude: ['**/*.shard1', '**/*.shard2', '**/*.weights_manifest.json'], esbuild: { drop: isProduction ? ['console', 'debugger'] : [], // minifyIdentifiers: true, minifySyntax: true, minifyWhitespace: true, }, plugins: [ vue(), // 生产环境移除 devTools 插件(减少产物体积) ...(!isProduction ? [vueDevTools()] : []), // face-api.js 模型文件 MIME 类型修复插件 faceModelsMimeTypePlugin(), AutoImport({ resolvers: [ElementPlusResolver()], imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'], dts: 'src/auto-imports.d.ts', eslintrc: { enabled: true }, }), Components({ resolvers: [ElementPlusResolver()], dts: 'src/components.d.ts', dirs: ['src/components'], }), basicSsl(), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, // ====== 增强版生产构建配置 ====== build: { outDir: 'dist', assetsDir: 'assets', // 生产环境 sourcemap 配置(可选:隐藏源码但保留行映射) sourcemap: isProduction ? 'hidden' : true, // chunk 分割策略(优化加载性能) rollupOptions: { output: { manualChunks: { // 将第三方库单独分包 'element-plus': ['element-plus', '@element-plus/icons-vue'], vendor: ['vue', 'vue-router', 'pinia'], utils: ['axios', 'dayjs', 'crypto-js', '@vueuse/core'], }, // 文件名带 hash(缓存优化) chunkFileNames: 'assets/js/[name]-[hash].js', entryFileNames: 'assets/js/[name]-[hash].js', assetFileNames: 'assets/[ext]/[name]-[hash].[ext]', }, }, // 压缩配置 minify: 'esbuild', // 大文件警告阈值(默认500KB,可调整) chunkSizeWarningLimit: 1000, }, // 生产环境不显示错误遮罩 define: { __VUE_PROD_DEVTOOLS__: 'false', }, server: { host: true, port: 9999, open: true, https: {}, proxy: { '/api': { target: env.VITE_API_BASE_URL, changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), }, // 将 /config.json 代理到 h5 域名,避免开发环境跨域 '/config.json': { target: env.VITE_EXE_DOWNLOAD_BASE_URL || env.VITE_UPDATE_URL, changeOrigin: true, secure: true, }, }, }, } })