前言
Vite 凭借极快的冷启动和热更新体验迅速成为主流构建工具。但开发时基于 ESM 的按需编译与生产打包基于 Rollup 的机制截然不同,理解这两层关系是掌握 Vite 打包的关键。
一、开发 vs 生产:两套机制
Vite 在开发和打包时使用不同的策略:
| 阶段 |
引擎 |
原理 |
| 开发 |
esbuild |
预构建依赖 + ESM 按需编译,毫秒级冷启动 |
| 生产 |
Rollup |
全量打包,Tree-Shaking、代码分割、压缩 |
为什么不用 esbuild 打包?
esbuild 在代码分割和 CSS 处理上仍有局限,Rollup 生态成熟、插件丰富,是目前的最优解。
二、Rollup 打包流程
Vite 生产构建本质上是调用 Rollup 并传入内部插件链:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const { rollup } = require('rollup')
const bundle = await rollup({ input: 'index.html', plugins: [ viteResolvePlugin(), viteCSSPlugin(), viteAssetPlugin(), viteHTMLPlugin(), ] })
await bundle.write({ dir: 'dist', format: 'es', manualChunks: { } })
|
入口是 index.html,Vite 会在构建时解析 HTML 中的 <script> 和 <link> 标签来收集依赖。
三、代码分割(分包策略)
不做分包会导致业务代码全打进一个大文件,首屏加载极慢。
默认分包
Vite 自动将 node_modules 中的依赖按以下规则分 chunk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function splitVendorChunkPlugin() { return { name: 'vite:split-vendor-chunk', config(config) { config.build = config.build || {} config.build.rollupOptions = config.build.rollupOptions || {} config.build.rollupOptions.output = { manualChunks(id) { if (id.includes('node_modules')) { return 'vendor' } } } } } }
|
自定义分包(推荐)
实际项目建议按模块大小和使用频率精细拆分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| export default defineConfig({ build: { rollupOptions: { output: { manualChunks: { 'vue-vendor': ['vue', 'vue-router', 'pinia'], 'ui-vendor': ['ant-design-vue', '@ant-design/icons-vue'], 'util-vendor': ['lodash-es', 'dayjs', 'axios'], 'echarts-vendor': ['echarts'], } } } } })
|
动态分包(推荐生产环境)
1 2 3 4 5 6
| manualChunks(id) { if (id.includes('node_modules')) { return id.toString().split('node_modules/')[1].split('/')[0] } }
|
分包追求的目标:低频变动的依赖拆成独立 chunk → 利用浏览器缓存 → 二次访问提速。
四、常用打包配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { visualizer } from 'rollup-plugin-visualizer' import compression from 'vite-plugin-compression'
export default defineConfig({ plugins: [vue()], build: { outDir: 'dist', assetsDir: 'assets', chunkSizeWarningLimit: 500, sourcemap: false, cssCodeSplit: true, minify: 'esbuild', terserOptions: { compress: { drop_console: true, drop_debugger: true, } }, rollupOptions: { output: { entryFileNames: 'js/[name]-[hash:8].js', chunkFileNames: 'js/[name]-[hash:8].js', assetFileNames: 'assets/[name]-[hash:8][extname]', manualChunks: { 'vue-vendor': ['vue', 'vue-router', 'pinia'], } } } } })
|
五、打包体积分析
使用 rollup-plugin-visualizer
1
| npm i -D rollup-plugin-visualizer
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({ plugins: [ vue(), visualizer({ open: true, gzipSize: true, brotliSize: true, }) ] })
|
执行 npm run build 后自动打开可视化面板,一眼看出是哪个包拖垮了体积。
六、常见优化手段
1. 按需引入
1 2 3 4 5
| import { Button, Table, Form } from 'ant-design-vue'
|
2. Gzip / Brotli 压缩
1
| npm i -D vite-plugin-compression
|
1 2 3 4 5 6 7 8 9 10
| import compression from 'vite-plugin-compression'
export default defineConfig({ plugins: [ compression({ algorithm: 'gzip', ext: '.gz' }), compression({ algorithm: 'brotliCompress', ext: '.br' }), ] })
|
3. 图片压缩
1
| npm i -D vite-plugin-imagemin
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import viteImagemin from 'vite-plugin-imagemin'
export default defineConfig({ plugins: [ viteImagemin({ gifsicle: { optimizationLevel: 3 }, mozjpeg: { quality: 80 }, pngquant: { quality: [0.8, 0.9] }, svgo: { plugins: [{ name: 'removeViewBox', active: false }] } }) ] })
|
4. CDN 加速
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import cdn from 'vite-plugin-cdn-import'
export default defineConfig({ plugins: [ cdn({ modules: [ { name: 'vue', var: 'Vue', path: 'vue.global.prod.js' }, { name: 'vue-router', var: 'VueRouter' }, { name: 'pinia', var: 'Pinia' }, { name: 'axios', var: 'axios' }, ] }) ] })
|
CDN 引入后这些依赖不打入 bundle,配合 externals 配置大幅缩减打包体积。
5. 优化总结清单
| 优化点 |
预期收益 |
| 按需引入 UI 库 |
减少 200KB+ |
| Gzip + Brotli |
压缩 70%+ |
| 图片压缩 |
减少 50-90% |
| 分包策略 |
首屏加载减半 |
| CDN 外链 |
核心包体积降为 0 |
| 移除 console/debugger |
轻微体积优化 |
| sourcemap 关闭 |
安全 + 体积 |
总结
- Vite 开发用 esbuild(ESM 按需),打包用 Rollup(全量构建)
- 分包策略是最重要的生产配置,决定首屏加载速度和缓存命中率
manualChunks 建议将 Vue/UI 库/ECharts 等大依赖独立拆出
- 配合
rollup-plugin-visualizer 分析体积,针对性优化
- 生产标配:分包 + Gzip + 按需引入 + 图片压缩
内容由 AI 生成,仅供参考。本文发布于 码上学习,转载请注明出处。