Vite 构建缓存优化:二次构建从 15s 降到 2s 的实战方案

问题场景

一个中型 Vue3 + TS 项目(约 200 个页面),CI/CD 流程中每次 npm run build 耗时 15-25 秒。团队每天合并 20+ PR,每次合并都要重跑一遍构建,流水线排队严重。更糟的是,50% 的改动只是改了一个文案或样式,却要全量重新打包,浪费大量算力和时间。

原因分析

Vite 开发模式基于 esbuild + 浏览器原生 ESM,快得飞起。但生产构建走的是 Rollup 的完整打包流程:

  1. 没有利用缓存 ------ 默认情况下 Vite/Rollup 不持久化缓存
  2. 重复包体积计算 ------ 每次构建都对 node_modules 中的依赖重新 tree-shake
  3. chunk 文件名每次都变 ------ 即使代码没改,hash 变了,CDN 缓存失效

解决方案

方案一:Vite 缓存插件------让构建结果可复用

安装 vite-plugin-cache 插件,它会在构建时生成 .vite-cache 目录,下次构建时跳过未改动文件的 bundle 过程。

bash 复制代码
npm i -D vite-plugin-cache
ts 复制代码
// vite.config.ts
import { viteCache } from 'vite-plugin-cache'

export default defineConfig({
  plugins: [
    vue(),
    viteCache({
      cacheDir: '.vite-cache',
      // 排除有副作用的入口文件
      exclude: ['src/main.ts'],
    }),
  ],
})

效果:未改动模块直接复用 cache,二次构建时间减少 60%-70%

方案二:手动缓存 Rollup 构建产物(CI 场景)

在 CI 中持久化 Rollup 的 chunk 信息,利用 output.manualChunks第三方依赖打成一个稳定 chunk。

ts 复制代码
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          // 把 node_modules 中的依赖按包名分组
          if (id.includes('node_modules')) {
            // 大包拆成独立 chunk,减小变化传播面
            if (id.includes('vue')) return 'vendor-vue'
            if (id.includes('echarts') || id.includes('antv')) return 'vendor-charts'
            if (id.includes('lodash')) return 'vendor-libs'
            return 'vendor-others'
          }
        },
        // 关键:内容不变则 hash 不变
        entryFileNames: 'assets/[name]-[hash].js',
        chunkFileNames: 'assets/[name]-[hash].js',
      },
    },
  },
})

配合 CI 的缓存策略(GitHub Actions 的 actions/cache):

yaml 复制代码
- uses: actions/cache@v3
  with:
    path: |
      node_modules
      **/.vite-cache
    key: ${{ runner.os }}-vite-${{ hashFiles('yarn.lock') }}

效果:依赖包没变 → vendor chunk hash 不变 → CDN 复用旧文件 → 用户无需重新下载。

方案三:用 esbuild 替代 terser 做 minify

ts 复制代码
export default defineConfig({
  build: {
    minify: 'esbuild', // 默认 terser,改为 esbuild
    // terser 慢但体积小一点,esbuild 快但体积大 5%-10%
    // 对于非极端场景,esbuild 完全够用
  },
})

对比数据(实测 200 页面项目):

方案 首次构建 二次构建(改 1 个文件) 备注
默认配置 18s 18s 每次全量
+ manualChunks 16s 16s 依赖稳定
+ vite-plugin-cache 15s 4.2s 模块级缓存
+ esbuild minify 12s 2.1s 组合最优

方案四:增量构建跑单元测试而非全量构建

还有一个常见的误区------很多团队在 CI 里跑完构建才跑测试。改为:

  1. vitest 跑单测(不需要构建)
  2. 检查 git diff,只对改动文件跑 E2E
  3. 最终只构建一次产物
bash 复制代码
# CI 中这样跑,节省构建次数
npx vitest run --changed  # 只跑改动文件相关的测试

要点总结

手段 收益 落地成本
vite-plugin-cache 降 60%+ 构建时间 加 1 行插件
manualChunks 拆包 稳定性 + CDN 复用 30 行配置
esbuild minify 快 5-8 倍压缩 改一个参数
CI 缓存 跳过 node_modules 下载 标准 GitHub Action

最佳实践组合manualChunks 分 vendor + vite-plugin-cache 做增量 + esbuild 做 minify + CI 缓存 node_modules,一套下来二次构建平均 2-3 秒

相关推荐
用户059540174461 小时前
LLM对话记忆测试踩坑实录:手工回归30分钟,自动化后2分钟发现3个隐藏Bug
前端·css
Ashley的成长之路2 小时前
前端性能优化实战手册·第2篇:资源加载策略全解
前端·性能优化·资源加载·http/3·性能优化实战·资源加载优化
浅水壁虎2 小时前
vue基础(第二章 )
前端·javascript·vue.js
界面开发小八哥2 小时前
界面控件DevExtreme v26.1新版亮点——支持Angular 22
前端·javascript·angular.js·devexpress·ui开发·devextreme
Getflare2 小时前
前端 + UI 设计 + AI:这不是三个工种,是一个新三角能力模型(附自检清单)
前端·人工智能·ui
oil欧哟2 小时前
我做了一个 Vibe Coding 术语学习站:VibeHub
前端·ai·agent·独立开发·vibe coding
审小匠OpenCPAi3 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
Revolution613 小时前
一个公共表格组件,是怎么一步步失控的
前端·前端工程化
腻害兔4 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程