import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import { VitePWA } from 'vite-plugin-pwa' import { visualizer } from 'rollup-plugin-visualizer' import viteCompression from 'vite-plugin-compression' import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite' // https://vitejs.dev/config/ export default defineConfig(({ mode, command }) => { const isProduction = mode === 'production' const isAnalyze = mode === 'analyze' return { base: isProduction ? '/emotion-museum/' : '/', plugins: [ vue(), // 自动导入 AutoImport({ imports: [ 'vue', 'vue-router', 'pinia', '@vueuse/core', { 'vue-i18n': ['useI18n'] } ], resolvers: [ElementPlusResolver()], dts: true, eslintrc: { enabled: true } }), // 组件自动导入 Components({ resolvers: [ElementPlusResolver()], dts: true }), // PWA支持 VitePWA({ registerType: 'autoUpdate', includeAssets: ['favicon.ico', 'apple-touch-icon.png'], manifest: { name: '情绪博物馆', short_name: '情绪博物馆', description: '记录情绪,分享心情的温暖空间', theme_color: '#4A90E2', background_color: '#ffffff', display: 'standalone', icons: [ { src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png' }, { src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png' } ] }, workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'] } }), // 国际化支持 VueI18nPlugin({ include: resolve(__dirname, './src/i18n/locales/**') }), // Gzip压缩(仅生产环境) isProduction && viteCompression({ verbose: true, disable: false, threshold: 10240, algorithm: 'gzip', ext: '.gz' }), // 构建分析(仅分析模式) isAnalyze && visualizer({ filename: 'dist/stats.html', open: true, gzipSize: true, brotliSize: true }) ].filter(Boolean), resolve: { alias: { '@': resolve(__dirname, 'src'), '~': resolve(__dirname, 'src') } }, define: { global: 'globalThis', __VUE_I18N_FULL_INSTALL__: true, __VUE_I18N_LEGACY_API__: false, __INTLIFY_PROD_DEVTOOLS__: false }, server: { port: 5173, open: true, proxy: { '/api': { target: 'http://localhost:19089', changeOrigin: true, secure: false }, '/ws': { target: 'ws://localhost:19089', ws: true, changeOrigin: true } } }, build: { outDir: 'dist', sourcemap: !isProduction, minify: isProduction ? 'terser' : false, terserOptions: isProduction ? { compress: { drop_console: true, drop_debugger: true, pure_funcs: ['console.log', 'console.info', 'console.debug'] }, mangle: { safari10: true } } : {}, rollupOptions: { external: (id) => { if (id.includes('echarts') && id.includes('extension')) { return true } return false }, output: { chunkFileNames: 'js/[name]-[hash].js', entryFileNames: 'js/[name]-[hash].js', assetFileNames: (assetInfo) => { const fileName = assetInfo.name || 'asset' const info = fileName.split('.') const ext = info[info.length - 1] if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)$/.test(fileName)) { return `media/[name]-[hash].${ext}` } if (/\.(png|jpe?g|gif|svg|webp|ico)$/.test(fileName)) { return `images/[name]-[hash].${ext}` } if (/\.(woff2?|eot|ttf|otf)$/.test(fileName)) { return `fonts/[name]-[hash].${ext}` } return `assets/[name]-[hash].${ext}` }, manualChunks: (id) => { // 第三方库分包 if (id.includes('node_modules')) { if (id.includes('vue') || id.includes('pinia') || id.includes('vue-router')) { return 'vue-vendor' } if (id.includes('element-plus')) { return 'element-plus' } if (id.includes('echarts')) { return 'echarts' } if (id.includes('lodash') || id.includes('dayjs') || id.includes('axios')) { return 'utils' } return 'vendor' } // 业务模块分包 if (id.includes('/src/views/')) { const pathSegments = id.split('/src/views/')[1].split('/') if (pathSegments.length > 1) { return `pages-${pathSegments[0]}` } } if (id.includes('/src/components/')) { return 'components' } } } }, // 构建性能优化 chunkSizeWarningLimit: 1000, reportCompressedSize: !isProduction, // 目标浏览器 target: ['es2015', 'chrome63', 'firefox67', 'safari12'] }, optimizeDeps: { include: [ 'vue', 'vue-router', 'pinia', 'element-plus', 'echarts', 'vue-echarts', '@vueuse/core', 'dayjs', 'lodash-es' ] } } })