Vue 3 + Vite 6 构建优化:2 分 33 秒压到 50 秒,vendor chunk 从 7.6MB 降到 2.4MB
一个 Vue 3 + Vite 6 项目,原始构建时间约 2 分 33 秒,最大 vendor chunk 达到 7.6MB。调整构建配置后,构建时间降到约 50 秒(提升约 68%),最大 chunk 降到 2.4MB。
改动集中在五处,下面按顺序记录。
1. 插件按环境差异化启用
不再让 dev / test / prod 共用一套插件,按环境启用不同的插件,避免不必要的开销。
- Legacy 插件会生成额外的 polyfill,开发和测试环境不需要。
- brotli 压缩计算非常耗时,测试环境只用 gzip 即可。
2. manualChunks 细粒度拆分
把 node_modules 按依赖分组拆开,避免所有第三方包挤进同一个 vendor:
build.rollupOptions.output.manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('vue') || id.includes('@vue') || id.includes('pinia') || id.includes('vue-router')) return 'vendor-vue';
if (id.includes('element-plus') || id.includes('@element-plus')) return 'vendor-element';
if (id.includes('cesium') || id.includes('@cesium')) return 'vendor-cesium';
if (id.includes('echarts') || id.includes('zrender')) return 'vendor-echarts';
return 'vendor-other';
}
}
3. 用 LightningCSS 替代默认 CSS 压缩器
build.cssMinify: 'lightningcss'
这里有一个坑:不要同时配置 css.transformer: 'lightningcss'。它会与 UnoCSS 的 @apply 指令冲突,导致 @apply 生成的样式(例如 skew-x-150)不生效。也就是说,cssMinify 换成 LightningCSS 做压缩是可以的,但 transformer 仍然交给 UnoCSS 那条链路。
4. 提高 Rollup 并行文件操作数
build.rollupOptions.maxParallelFileOps: 10 // 默认 5
5. 大型依赖动态导入
不常用的大依赖改为延迟加载,不进入首屏加载路径。
拆包踩到的两个坑
细粒度拆分不是对所有依赖都成立,有两个包必须留在 vendor-other:
- d3:内部模块之间存在循环依赖,单独拆分会破坏初始化顺序,不要给它单独分支,合并到
vendor-other。 - video.js:它和它的插件模块之间依赖关系复杂,单独拆分同样会破坏初始化顺序,也合并到
vendor-other。
验证方式
用 rollup-plugin-visualizer 生成构建报告,查看各 chunk 的体积分布;同时对比优化前后的构建时间与产物总体积。
结论
- 并非所有依赖都适合单独拆分,拆分前要考虑循环依赖。
- 引入新工具(如 LightningCSS)要验证它与现有工具链的兼容性,
cssMinify与css.transformer是两回事。 - 渐进式优化,每次改动后都验证功能正常。