import { defineConfig, loadEnv } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' import { fileURLToPath } from 'url' import vueDevTools from 'vite-plugin-vue-devtools' import viteCompression from 'vite-plugin-compression' import Components from 'unplugin-vue-components/vite' import AutoImport from 'unplugin-auto-import/vite' import ElementPlus from 'unplugin-element-plus/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import tailwindcss from '@tailwindcss/vite' // import { visualizer } from 'rollup-plugin-visualizer' export default ({ mode }: { mode: string }) => { const root = process.cwd() const env = loadEnv(mode, root) const { VITE_VERSION, VITE_PORT, VITE_BASE_URL, VITE_API_URL, VITE_API_PROXY_URL } = env const isDev = mode === 'development' const isDockerBuild = mode === 'docker' const dropConsole = env.VITE_DROP_CONSOLE === 'true' console.log(`🚀 API_URL = ${VITE_API_URL}`) console.log(`🚀 VERSION = ${VITE_VERSION}`) return defineConfig({ define: { __APP_VERSION__: JSON.stringify(VITE_VERSION) }, base: VITE_BASE_URL, server: { port: Number(VITE_PORT), proxy: { '/api': { target: VITE_API_PROXY_URL, changeOrigin: true }, // Web端接口代理 - 转发到后端 /api 前缀(与 /api 一致走本地 backend) '/web': { target: VITE_API_PROXY_URL, changeOrigin: true, rewrite: (path) => `/api${path}` }, // 小程序端接口代理 '/mini': { target: VITE_API_PROXY_URL, changeOrigin: true, rewrite: (path) => `/api${path}` } }, host: true }, // 路径别名 resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), '@views': resolvePath('src/views'), '@imgs': resolvePath('src/assets/images'), '@icons': resolvePath('src/assets/icons'), '@utils': resolvePath('src/utils'), '@stores': resolvePath('src/store'), '@styles': resolvePath('src/assets/styles') } }, build: { target: 'es2015', outDir: 'dist', chunkSizeWarningLimit: 2000, // docker 镜像构建用 esbuild,内存占用远低于 terser(避免 Docker 内 OOM) minify: isDockerBuild ? 'esbuild' : 'terser', ...(isDockerBuild ? { esbuild: dropConsole ? { drop: ['console', 'debugger'] } : undefined } : { terserOptions: { compress: { drop_console: dropConsole, drop_debugger: dropConsole } } }), rollupOptions: { input: { main: path.resolve(__dirname, 'index.html'), 'oa-fc-host': path.resolve(__dirname, 'oa-fc-host.html') } }, dynamicImportVarsOptions: { warnOnError: true, exclude: [], include: ['src/views/**/*.vue'] } }, plugins: [ vue(), tailwindcss(), // 自动按需导入 API AutoImport({ imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'], dts: 'src/types/import/auto-imports.d.ts', resolvers: [ElementPlusResolver()], eslintrc: { enabled: true, filepath: './.auto-import.json', globalsPropValue: true } }), // 自动按需导入组件 Components({ dts: 'src/types/import/components.d.ts', resolvers: [ElementPlusResolver()] }), // 按需定制主题配置 ElementPlus({ useSource: true }), // docker 构建跳过预压缩,减少峰值内存;交付镜像由 Nginx 直接托管静态资源 ...(isDockerBuild ? [] : [ viteCompression({ verbose: false, disable: false, algorithm: 'gzip', ext: '.gz', threshold: 10240, deleteOriginFile: false }) ]), ...(isDev ? [vueDevTools()] : []) // 打包分析 // visualizer({ // open: true, // gzipSize: true, // brotliSize: true, // filename: 'dist/stats.html' // 分析图生成的文件名及路径 // }), ], // 依赖预构建:避免运行时重复请求与转换,提升首次加载速度 optimizeDeps: { include: [ 'echarts/core', 'echarts/charts', 'echarts/components', 'echarts/renderers', 'xlsx', 'xgplayer', 'crypto-js', 'file-saver', 'vue-img-cutter', 'element-plus/es', 'element-plus/es/components/*/style/css', 'element-plus/es/components/*/style/index' ] }, css: { preprocessorOptions: { // sass variable and mixin scss: { additionalData: ` @use "@styles/core/el-light.scss" as *; @use "@styles/core/mixin.scss" as *; ` } }, postcss: { plugins: [ { postcssPlugin: 'internal:charset-removal', AtRule: { charset: (atRule) => { if (atRule.name === 'charset') { atRule.remove() } } } } ] } } }) } function resolvePath(paths: string) { return path.resolve(__dirname, paths) }