import { defineConfig, loadEnv } from 'vite'; import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; import vue from '@vitejs/plugin-vue'; import Components from 'unplugin-vue-components/vite'; import { VantResolver } from 'unplugin-vue-components/resolvers'; import { viteVConsole } from 'vite-plugin-vconsole'; import path from 'path'; import viteCompression from 'vite-plugin-compression'; const resolve = (dir) => path.resolve(__dirname, dir); const timeStamp = new Date().getTime(); export default ({ command, mode }) => { // 获取环境变量 const env: Partial = loadEnv(mode, process.cwd()); // https://vitejs.dev/config/ return defineConfig({ publicDir: resolve('public'), //静态资源服务的文件夹 define: { 'process.env': env, // 配置 Vue 的水合不匹配详情特性标志 // 在开发环境下启用以便于调试 // 在生产环境下禁用以优化包体积 __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: mode === 'development' ? 'true' : 'false', }, plugins: [ vue(), Components({ resolvers: [VantResolver()], }), // gzip压缩 生产环境生成 .gz 文件 viteCompression({ verbose: true, disable: false, threshold: 10240, algorithm: 'gzip', ext: '.gz', }), createSvgIconsPlugin({ // 指定需要缓存的图标文件夹 iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')], // 指定symbolId格式 symbolId: 'icon-[dir]-[name]', /** * 自定义插入位置 * @default: body-last */ // inject?: 'body-last' | 'body-first' /** * custom dom id * @default: __svg__icons__dom__ */ // customDomId: '__svg__icons__dom__', }), viteVConsole({ entry: resolve('src/main.ts'), localEnabled: env.VITE_BUILD_VCONSOLE === 'true', enabled: env.VITE_BUILD_VCONSOLE === 'true', config: { maxLogNumber: 1000, theme: 'light', }, }), ], // 配置别名 resolve: { alias: { '@': resolve('src'), web3: 'web3/dist/web3.min.js', }, // 导入时想要省略的扩展名列表 extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], }, optimizeDeps: { exclude: ['@vite/client', '@vite/env'], }, css: { // css预处理器 preprocessorOptions: { scss: { additionalData: '@import "@/assets/styles/main.scss";', }, }, }, //启动服务配置 server: { host: '0.0.0.0', port: 8000, open: true, // 自动在浏览器打开 proxy: { '/dcserv': { target: 'https://api.shuifeng.cc', changeOrigin: true, rewrite: (path) => path.replace(/^\/dcserv/, ''), }, }, hmr: { overlay: false, }, }, // 打包配置 build: { //浏览器兼容性 "esnext"|"modules" target: 'modules', //指定输出路径 outDir: 'dist', //生成静态资源的存放路径 assetsDir: 'assets', //启用/禁用 CSS 代码拆分 cssCodeSplit: true, sourcemap: env.VITE_BUILD_SOURCEMAP === 'true', assetsInlineLimit: 10240, chunkSizeWarningLimit: 1500, // chunk 大小警告的限制(以 kbs 为单位) minify: 'terser', terserOptions: { compress: { keep_infinity: true, // 防止 Infinity 被压缩成 1/0,这可能会导致 Chrome 上的性能问题 drop_console: env.VITE_BUILD_DROP_CONSOLE === 'true', drop_debugger: true, }, }, rollupOptions: { input: { main: resolve('index.html'), }, output: { entryFileNames: `js/[name]-[hash].${timeStamp}.js`, chunkFileNames: `js/[name]-[hash].${timeStamp}.js`, assetFileNames: `[ext]/[name]-[hash].${timeStamp}.[ext]`, manualChunks(id) { if (!id.includes('node_modules')) return; const pkg = id.match(/node_modules\/(?:\.pnpm\/)?((?:@[^/]+\/)?[^/@]+)/)?.[1]; if (!pkg) return; // vue 及其 @vue/* 必须同 chunk,拆开会导致 TDZ:Cannot access 'isFunction' before initialization if ( ['vue', 'vue-router', 'pinia', 'pinia-plugin-persistedstate'].includes(pkg) || pkg.startsWith('@vue/') ) { return 'vue-vendor'; } if (pkg === 'vant') { return 'vant'; } // 仅被懒加载页面使用的重库:不进共享 vendor,避免首包被拖大 if (['xgplayer-hls.js', 'xgplayer', 'html5-qrcode', 'pinyin-pro', 'vuedraggable-es', 'spark-md5'].includes(pkg)) { return; } return 'vendor'; }, }, }, }, }); };