首页技术专题博客目录我的收藏关于与联系

打包体积战争:一次把首屏 JS 从 1.2MB 打到 420KB 的实战记录

这不是一篇「Tree Shaking 原理科普」,而是一次真实的减包过程:从被产品吐槽「页面怎么这么慢」,到掏出 webpack-bundle-analyzer 一刀一刀砍依赖,中间有很多不体面的妥协和取舍。

事情是怎么暴露出来的

首屏 JS 1.2MB 不是一天长出来的。项目上线两年,业务一直在加,组件库一直在换,埋点 SDK 换了两轮,谁也没认真看过打包报告。

真正被揪出来,是因为运营做了一次新用户调研。用户的原话很扎心:

「第一次打开时候,我以为是我网不好,后来发现你们网站就是慢。」

产品拿着这句话来找我们的时候,我顺手跑了一下 Lighthouse——4G 网络模拟下首屏 TTI 接近 8 秒,Performance 评分 39。

先看清楚敌人长什么样

第一步没有上来就改配置,而是打开了 webpack-bundle-analyzer。那张「宇宙飞船图」第一次在大屏上放出来的时候,全组都沉默了几秒。

  • 某个图表库单包就占了 300KB(而且我们只用到了两种图)
  • 有两个日期库同时存在,一个是 moment,一个是 dayjs
  • 有一段老的富文本编辑器,已经没人能说清楚哪里还在用

我们把这张图打印出来,贴在了工位后面的白板上,旁边用红笔写了一句:

「先把肉眼可见的浪费砍掉,再谈高级优化。」

第一轮:粗暴砍依赖(1.2MB → 720KB)

第一轮我们基本没动构建配置,只干了三件事:

  1. 把整包引入的图表库换成了 echarts/core 按需引入,只保留折线图和柱状图。
  2. 全局搜索 moment 的使用,能换成原生 Date 的就直接换,其余用 dayjs 统一替代。
  3. 把富文本编辑器拆出去了,做成异步加载,只有在配置公告时才加载。

这一轮做完,首屏 JS 体积从 1.2MB 掉到了 720KB。Lighthouse 分数直接涨到了 62。 产品那边第一次在群里发了句:

「确实快了一点,至少不会卡一整条 loading 条了。」

第二轮:拆路由、拆首屏(720KB → 420KB)

720KB 还是偏大,但我们已经把「最肥的肉」砍了一轮,接下来只能动结构了。

1. 路由级别的代码分割

原来的路由写法是传统的:

import Dashboard from './pages/Dashboard'; import UserCenter from './pages/UserCenter'; // ... 

我们统一改成了动态 import:

const Dashboard = lazy(() => import('./pages/Dashboard')); const UserCenter = lazy(() => import('./pages/UserCenter'));

并且刻意把首屏只保留「仪表盘」,其余子模块全拆到子 chunk 里。

2. 首页组件瘦身

仪表盘本身也很肥。各种图表、统计卡片、活动公告都堆在一起。 产品一开始不太愿意砍,我们后来给了一个很直观的对比:

  • 版本 A:首屏所有模块都加载完,TTI 6 秒
  • 版本 B:只保留「今日关键指标 + 待办」,其余模块懒加载,TTI 2.8 秒

最后达成的折中方案是: 首屏只保留「关键指标 + 待办 + 一个折线图」,其余模块在用户滚动到对应区域时再加载。

第三轮:一些容易被忽略的小细节

后面我们又做了几件小事,单看收益不大,但叠加起来效果还不错:

  • 把几个「一次性弹出」的引导组件改成了运行时动态 import。
  • 把 SVG 图标从某个第三方库换成了自建的 iconfont,减少了一半的 icon 体积。
  • 给 webpack 配了 splitChunks.cacheGroups,把基础库单独抽出来缓存。

做完这些之后,首屏 JS 体积最终稳定在 420KB 左右,Lighthouse 的 Performance 分数在我们常见的机型上能跑到 82~88。

这件事对团队的影响

减包这件事做完之后,最明显的变化不是「页面变快了」,而是: 再有人想引一个新库的时候,会下意识先看一眼它的体积。

我们还在 PR 模板里加了一行:

- [ ] 是否引入了新依赖?如果是,请在描述里写清楚原因和体积影响。

一开始大家觉得这行很烦,但过了两个月,已经成了一个天然的过滤器:很多「只是为了图省事」的依赖,引都懒得引了。

最后的感受

现在再看那次减包,技术上其实没有多高深,很多操作都很常规。真正难的地方,在于说服自己和团队: 这不是一波「性能优化 KPI」,而是一件会长期改变我们写前端方式的事。

如果你们的首屏包现在也已经奔着 1MB 去了,不妨先别立什么「性能优化 OKR」,先把 bundle-analyzer 打开,在大屏上投一次。 把那张图贴到墙上,比任何性能专项动员会都更有说服力。

评论区