import path from 'node:path'; import vue from '@vitejs/plugin-vue'; import vueJsx from '@vitejs/plugin-vue-jsx'; import type { ConfigEnv, UserConfig } from 'vite'; import { loadEnv } from 'vite'; import compression from 'vite-plugin-compression'; import { viteMockServe } from 'vite-plugin-mock'; import svgLoader from 'vite-svg-loader'; /** 工作目录用于解析环境变量文件和项目内资源路径。 */ const CWD = process.cwd(); /** 根据当前 Vite 模式加载环境变量并组装应用构建和开发服务器配置。 */ export default ({ mode }: ConfigEnv): UserConfig => { /** 从当前模式对应的 env 文件读取站点基路径和 API 代理前缀。 */ const { VITE_BASE_URL, VITE_API_URL_PREFIX } = loadEnv(mode, CWD); return { base: VITE_BASE_URL, resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, css: { preprocessorOptions: { less: { modifyVars: { hack: `true; @import (reference) "${path.resolve('src/style/variables.less')}";`, }, math: 'strict', javascriptEnabled: true, }, }, }, // 注册 Vue/JSX、开发 mock、SVG 导入及 gzip 压缩等构建插件。 plugins: [ vue(), vueJsx(), viteMockServe({ mockPath: 'mock', enable: true, }), svgLoader(), compression({ algorithm: 'gzip', // 压缩算法 filter: /\.(html|js|css|json|txt|ico|svg|png)(\?.*)?$/i, // 需要压缩的文件 ext: '.gz', // 压缩后缀 threshold: 4096, // 大于 4KB 的文件将会被压缩 deleteOriginFile: false, // 压缩后删除对应的源文件 compressionOptions: { level: 9, // 压缩级别,1~9,压缩级别(数值)越高,压缩的越狠 }, }), ], // 本地开发服务设置和 API 请求代理。 server: { port: 3002, host: '0.0.0.0', allowedHosts: true, proxy: { [VITE_API_URL_PREFIX]: 'http://127.0.0.1:3000/', }, }, // https://github.com/vueuse/vueuse/issues/5387#issuecomment-4734186040 // 控制产物文件名、依赖分包策略及第三方包构建警告。 build: { chunkSizeWarningLimit: 1000, rolldownOptions: { onLog(level, log, defaultHandler) { if (log.code === 'INVALID_ANNOTATION') return null; else defaultHandler(level, log); }, // [name] output: { // 代码块文件名 chunkFileNames: 'assets/js/xiaohh-[hash].js', // 入口文件名 entryFileNames: 'assets/xiaohh-[hash].js', assetFileNames(assetInfo) { // 文件名 const fileName = assetInfo.names[0]; if (fileName.endsWith('.svg') || fileName.endsWith('.png') || fileName.endsWith('.jpg')) { // 判断如果是 svg, png, jpg 等图片文件,则放入 assets/img 文件夹当中 return 'assets/img/xiaohh-[hash].[ext]'; } else if (fileName.endsWith('.css')) { // 如果是 css 文件,则放入 assets/css 文件夹当中 return 'assets/css/xiaohh-[hash].[ext]'; } else { // 如果是其他文件,则直接放入 assets 文件夹当中 return 'assets/xiaohh-[hash].[ext]'; } }, // 将依赖和 SVG 拆分为独立 chunk,改善浏览器缓存粒度。 manualChunks(id) { if (id.includes('node_modules')) { // node_modules 当中不同依赖打包成不同的文件 return id.split('node_modules/')[1].split('/')[0]; } else if (id.endsWith('.svg')) { // 如果是 svg 文件打包成 js 文件,则每个 svg 文件单独一个 js 文件 return ( id .split('/') .pop() ?.replace(/\.svg$/i, '') || '' ); } }, }, onwarn(warning, defaultHandler) { // @vueuse/core 中的 PURE 注释在 Rolldown 中位置无效,忽略 if (warning.code === 'INVALID_ANNOTATION' && warning.id?.includes('@vueuse/core')) { return; } defaultHandler(warning); }, }, }, }; };