构建工具的一些思考:一个北漂(伪)程序员的深夜碎碎念
上周五晚上十点半,我正戴着 AirPods 听着 Lofi Girl 的 beat 写代码,突然收到测试群里@全体成员的消息:“线上静态资源加载超时了,用户投诉页面白屏!”——那一刻,我真的想把 MacBook 直接从窗户扔出去。房贷还没还完,项目却在搞我。
虽然我现在人在成都,过着“慢节奏”的伪北漂生活(其实是被高房租劝退后逃回来的),但工作强度一点没少。我们团队最近在搞一个 AI 驱动的运营中台,产品经理天天催“要快!要轻!要能秒开!”,结果构建脚本一跑就是 5 分钟,上线前还得祈祷别出错。于是,我被迫重新审视起那些被我们当成“黑盒”用的构建工具——Webpack、Vite、Rollup、甚至 Turbopack……它们到底是救星,还是背锅侠?
被逼上梁山:为什么又得折腾构建?
事情起源于上个月的一次性能复盘会。运维甩出一组数据:我们的管理后台首屏加载时间平均 4.8s,在弱网下直接飙到 8s+。老板一听就急了:“这体验怎么搞运营?用户都跑了!”——对,你没看错,运营成了压垮骆驼的最后一根稻草。
更扎心的是,我朋友上周跳槽面试,被问:“你们项目的构建流程是怎么优化的?”他支支吾吾说“用了 Webpack splitChunks”,结果面试官反问:“那你知道 splitChunks 的 cacheGroups 是怎么影响长期缓存的吗?”他当场懵了。回来跟我吐槽:“现在连面试题都卷到构建工具了?”
我苦笑:可不是嘛。以前觉得构建工具就是配个 config,跑通就行。现在发现,它直接决定了你的 bundle 大小、加载速度、缓存策略,甚至影响 SEO 和转化率——对,就是那个和运营强相关的指标。
Webpack:老将不死,只是臃肿
我们主项目还在用 Webpack 5。不是不想换,是不敢换。毕竟几十个页面、上百个模块,重构成本太高。但它的慢是真的肉眼可见:
- 开发模式热更新经常卡 10s+
- 生产构建时内存爆到 4GB
- 某次不小心把 node_modules 打包进 vendor,上线后 CDN 费用翻倍(财务找我谈话时我差点跪下)
后来我花了一周时间做优化,核心思路就两个字:拆 和 缓。
// webpack.config.js 片段
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
enforce: true,
priority: 10
},
// 关键:按业务模块拆分
dashboard: {
test: /[\\/]src[\\/]pages[\\/]dashboard/,
name: 'dashboard',
chunks: 'all',
enforce: true
}
}
},
runtimeChunk: 'single'
}
加上 hard-source-webpack-plugin 做持久化缓存后,二次构建时间从 210s 降到 68s。虽然还是慢,但至少不用每次喝完一杯咖啡才能看到改动效果了。
不过说实话,Webpack 的配置就像写散文——自由但容易跑偏。有一次我把 minimize 关了调试,忘了打开,上线后 bundle 大了 3 倍,被运维追着骂了三天。
Vite:真香,但别盲目上头
新搞的 AI 实验项目,我果断上了 Vite。启动速度飞快,HMR 基本无感,ESBuild + Rollup 的组合拳打得漂亮。但你以为这就完了?Too young。
问题出在兼容性上。我们有些老组件用了 CommonJS 模块,Vite 默认不支持。结果本地跑得好好的,CI 流水线一跑就报错:
[vite] error during build:
Error: 'default' is not exported by node_modules/old-lib/index.js
查了半天才发现得加 vite-plugin-commonjs。更坑的是,某些动态 import() 语法在生产构建时会被 Rollup 静态分析搞乱路径,导致懒加载失败——用户点“数据分析”按钮,页面直接 404。
所以我的建议是:新项目可以冲 Vite,老项目迁移务必谨慎。别被“快”字蒙蔽了双眼,生态兼容性才是深水炸弹。
性能对比:数字不会骗人
为了说服团队 leader 支持我重构构建流程,我做了个简单 benchmark(基于同一套 React + Ant Design 代码):
| 工具 | 开发启动时间 | HMR 更新时间 | 生产构建时间 | Bundle 大小 (gzip) |
|---|---|---|---|---|
| Webpack 5 | 8.2s | 3.1s | 124s | 1.8MB |
| Vite 4 | 0.4s | 0.1s | 28s | 1.6MB |
| Turbopack (alpha) | 0.3s | 0.05s | N/A (dev only) | - |
注:Turbopack 目前仅支持开发环境,且对 Next.js 以外框架支持有限。
看到 Vite 的构建时间只有 Webpack 的 1/4,leader 终于点头让我试点。不过他也补了句:“别整崩了,下周双11大促,崩了你赔运营损失。”
构建优化 ≠ 工具替换
很多人以为换工具就能解决问题,其实不然。我在优化过程中踩过几个经典坑:
- 过度拆包:一开始我把每个 npm 包都单独拆成 chunk,结果 HTTP 请求从 5 个变成 50 个,首屏反而更慢了(TCP 连接开销太大)
- 忽略缓存策略:没配好
contenthash,导致用户每次刷新都要重新下载所有 JS,CDN 缓存形同虚设 - 开发体验牺牲太多:为了极致压缩,关掉 sourceMap,结果线上报错根本没法 debug
真正的优化,应该围绕业务场景展开。比如我们的运营后台,90% 用户只用 3 个核心功能,那我就把其他模块全做成动态 import,首屏 bundle 直接砍掉 40%。
// 动态导入非核心模块
const ReportPage = lazy(() => import('@/pages/Report'));
const SettingsPage = lazy(() => import('@/pages/Settings'));
配合 webpackPrefetch 提前加载,用户体验几乎无损。
最后一点真心话
作为一个月供 7k 的“伪北漂”,我其实挺怕折腾这些底层东西的——万一搞砸了,绩效扣了,房贷咋办?但现实是,构建工具已经不再是“基建”,而是直接影响产品成败的关键环节。
现在每次写代码,我都会多问一句:这个依赖真的必要吗?这个功能值得放在首屏吗?能不能用原生 ES 模块替代?……这种“斤斤计较”,可能就是被房贷逼出来的职业素养吧(笑)。
如果你也在被构建速度折磨,或者正在准备面试被问到这类面试题,不妨从一个小模块开始优化。别想着一口吃成胖子,先让 bundle 小 100KB,再让构建快 10 秒——积少成多,总比线上事故后背锅强。
对了,昨晚那个白屏问题,最后定位到是 CDN 配置错了 Cache-Control,和构建工具无关……但这段排查经历,又让我对整个交付链路有了更深的理解。果然,程序员的成长,都是用 bug 堆出来的。
(写完这篇,房贷还款日又近了一天。算了,继续听歌写代码吧。)

评论 0