Files
zhuangang/topics/frontend/webpack/scenarios/build-speed.md
T

3.8 KiB
Raw Blame History

id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week
id title type domain stack tags level prerequisites est_hours related week
frontend.webpack.scenario.build-speed 大型项目构建慢、包体积大:度量、优化和防退化 scenario frontend
webpack
fe-testing-perf
cicd
构建速度
包体积
splitChunks
持久化缓存
体积预算
CI
intermediate
frontend.webpack.build-optimization
2
frontend.webpack.interview
frontend.vite.scenario.webpack-to-vite
7

大型项目构建慢、包体积大:度量、优化和防退化

业务背景与问题

一个中台项目(webpack 5,几百个页面):CI 构建要十几分钟,发版排队;首页 JS 有几 MB,弱网用户首屏很慢;优化过一次,几个月后又变回去了。

约束

  • 短期内不能换构建工具(有大量自定义 loader 和插件)。
  • 优化要可量化,并且防止退化。

方案设计

  1. 先度量:
    • 构建速度:统计各 loader / plugin 耗时(速度分析插件或 --profile);
    • 体积:生成产物分析报告(webpack --json + 可视化工具),找出最大的依赖和重复依赖。
  2. 构建提速:
    • 开启 cache: { type: "filesystem" },CI 中缓存缓存目录;
    • babel-loader 换成 swc 类 loader,并用 include 只处理源码;
    • 生产构建关闭不需要的 source map 或使用更快的类型;
    • 类型检查与构建并行(单独的 tsc --noEmit 任务)。
  3. 体积优化:
    • 路由级懒加载;
    • 大依赖按需引入(图表库、组件库、日期库)或替换为更小的库;
    • splitChunks 按变化频率拆分第三方库;
    • 检查 sideEffects 让 tree shaking 生效。
  4. 防退化:在 CI 中设置体积预算(performance.maxEntrypointSize 或脚本对比上次的产物大小),超出就失败并提示。

关键代码

// webpack.config.js 片段
export default {
  cache: { type: "filesystem", buildDependencies: { config: [import.meta.filename] } },  // 配置变化时缓存失效
  module: {
    rules: [{ test: /\.[jt]sx?$/, include: path.resolve("src"), use: "swc-loader" }],
  },
  optimization: {
    runtimeChunk: "single",
    splitChunks: {
      chunks: "all",
      cacheGroups: {
        framework: { test: /[\\/]node_modules[\\/](vue|vue-router|pinia)[\\/]/, name: "framework", priority: 20 },
        vendors: { test: /[\\/]node_modules[\\/]/, name: "vendors", priority: 10 },
      },
    },
  },
  performance: { hints: "error", maxEntrypointSize: 500 * 1024, maxAssetSize: 300 * 1024 },  // 超预算直接构建失败
};

可运行的基础配置:examples/webpack-config。

取舍

选择 优点 缺点
在 webpack 内优化(本方案) 风险小,见效快 上限受 webpack 限制
迁移到 Rspack 配置大体兼容,速度提升大 部分插件需要验证
迁移到 Vite 开发体验最好 迁移成本高,见迁移场景

易错点

  • 没有度量就开始优化,改了很多却不知道哪项有效。
  • 持久化缓存没有配置 buildDependencies,改了配置却用了旧缓存。
  • 把所有第三方库打成一个巨大的 vendor,任何依赖升级都让整个文件缓存失效。
  • 只优化一次,没有预算和 CI 检查,很快退化。

面试怎么讲

“先度量:用速度分析和产物分析找到瓶颈,主要是 babel 处理了 node_modules 和一个整包引入的图表库。然后开启持久化缓存并在 CI 中缓存、换成 swc 类 loader、类型检查并行;体积上做路由懒加载、图表库按需引入、按变化频率拆包。最后在 CI 加体积预算防止退化。数据以实际测量为准,我会给出优化前后的对比。”