前端构建产物从 3MB 瘦到 400KB:一份可复用的治理流程
接手一个老项目时,首屏 JS 有 3.1MB(gzip 后仍有 900KB),移动端首屏白屏两秒多。治理过程没有什么黑科技,就是按顺序做对五件事。
一、先量化,别凭感觉优化
第一步是让体积可见。Vite 用 `rollup-plugin-visualizer`,Webpack 用 `webpack-bundle-analyzer`,产出一张 treemap。看完通常会发现二八定律极其明显:两三个依赖占了 60% 以上。没有这张图就动手,等于闭眼删代码。
二、找出"整包引入"的重灾区
老项目里最常见的三件事:`import _ from 'lodash'`、`import * as echarts from 'echarts'`、以及 UI 组件库全量注册。改法很机械但收益巨大:lodash 换成 `lodash-es` 按需引入或直接用原生方法;echarts 改成按需注册图表和组件;组件库改成按需加载(Vite 用 unplugin-vue-components / unplugin-react-components,Webpack 用 babel-plugin-import)。
三、把路由级代码切开
首屏只需要首页的代码。用动态 `import()` 做路由级懒加载,配 `Suspense` 或 loading 占位。这一步通常能砍掉 40% 的首屏体积,因为后台管理页往往比首页重得多。
四、依赖分层,Vendor 单独拆包并长期缓存
业务代码天天变,依赖几周才动一次,混在一个 chunk 里会让用户反复下载同样的库。用 `manualChunks` 把 react/vue、UI 库、图表库拆成稳定的 vendor chunk,配合文件名 hash 和长缓存,第二次访问的命中率会明显提升。
五、把体积阈值写进 CI
优化做完会被下次提交慢慢吃回去,所以必须有看门狗。最简单的是在构建后比较 gzip 后总体积,超过阈值就让流水线失败:
```bash
size=$(gzip -c dist/assets/index-*.js | wc -c)
[ "$size" -gt 450000 ] && echo "bundle too big: $size" && exit 1
```
更严谨的做法是用 `bundlesize` 或 `size-limit`,按 chunk 设阈值,PR 里直接显示 diff。
几个反直觉的结论:gzip 后 900KB 的包里,往往有 200KB 是没人用的 polyfill 和 moment 的 locale;图片和字体不占 JS 体积但占首屏时间,别只盯着 bundle;做完上面五步,真正让首屏变快的往往是"减少一次串行请求"而不是"再删 20KB 代码"。
还有一条容易被忽略的收益:删掉无用的 CSS。老项目里常常挂着一整套没人用的 UI 框架样式,用 PurgeCSS 或 Tailwind 的 JIT 之后,样式文件能从 300KB 降到 40KB。它不占 JS 体积,但会阻塞渲染,对首屏时间的影响和 JS 是同量级的。
治理是个持续动作,不是一次性项目。把它变成 CI 里的一条红线,比任何一次大重构都有效。
- 点赞
- 收藏
- 关注作者
评论(0)