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 |
|
|
大型项目构建慢、包体积大:度量、优化和防退化
业务背景与问题
一个中台项目(webpack 5,几百个页面):CI 构建要十几分钟,发版排队;首页 JS 有几 MB,弱网用户首屏很慢;优化过一次,几个月后又变回去了。
约束
- 短期内不能换构建工具(有大量自定义 loader 和插件)。
- 优化要可量化,并且防止退化。
方案设计
- 先度量:
- 构建速度:统计各 loader / plugin 耗时(速度分析插件或
--profile);
- 体积:生成产物分析报告(
webpack --json + 可视化工具),找出最大的依赖和重复依赖。
- 构建提速:
- 开启
cache: { type: "filesystem" },CI 中缓存缓存目录;
- babel-loader 换成 swc 类 loader,并用
include 只处理源码;
- 生产构建关闭不需要的 source map 或使用更快的类型;
- 类型检查与构建并行(单独的
tsc --noEmit 任务)。
- 体积优化:
- 路由级懒加载;
- 大依赖按需引入(图表库、组件库、日期库)或替换为更小的库;
splitChunks 按变化频率拆分第三方库;
- 检查
sideEffects 让 tree shaking 生效。
- 防退化:在 CI 中设置体积预算(
performance.maxEntrypointSize 或脚本对比上次的产物大小),超出就失败并提示。
关键代码
可运行的基础配置:examples/webpack-config。
取舍
| 选择 |
优点 |
缺点 |
| 在 webpack 内优化(本方案) |
风险小,见效快 |
上限受 webpack 限制 |
| 迁移到 Rspack |
配置大体兼容,速度提升大 |
部分插件需要验证 |
| 迁移到 Vite |
开发体验最好 |
迁移成本高,见迁移场景 |
易错点
- 没有度量就开始优化,改了很多却不知道哪项有效。
- 持久化缓存没有配置
buildDependencies,改了配置却用了旧缓存。
- 把所有第三方库打成一个巨大的 vendor,任何依赖升级都让整个文件缓存失效。
- 只优化一次,没有预算和 CI 检查,很快退化。
面试怎么讲
“先度量:用速度分析和产物分析找到瓶颈,主要是 babel 处理了 node_modules 和一个整包引入的图表库。然后开启持久化缓存并在 CI 中缓存、换成 swc 类 loader、类型检查并行;体积上做路由懒加载、图表库按需引入、按变化频率拆包。最后在 CI 加体积预算防止退化。数据以实际测量为准,我会给出优化前后的对比。”