移动端页面性能预算:从「感觉慢」到可量化
用户说慢,团队说还行,争论了两周没有结论。后来我们定了一个粗颗粒的性能预算,把首屏可交互时间、资源体积和请求数写成上线前必须过的三条线。文中给出预算的定法、测量口径,以及超预算时的取舍顺序。
一、争论是怎么开始的
争论的原话大概是这样的。使用方说「打开很慢,要等好几秒」,开发说「我这边挺快的」,测试说「看情况,有时候快」。三方都没有说谎,因为我们说的不是同一件事:对方用的是旧一点的手机和通勤路上的网络,开发用的是刚换的机器和办公室 Wi-Fi,测试说的是热启动之后的第二次打开。
我们为这件事开了两次会。第一次讨论「到底慢不慢」,第二次讨论「要不要优化」。两周过去,结论是没有结论,唯一确定的是大家都很累。
后来我意识到,问题不是谁对谁错,而是没有共同口径。没有口径,任何一次测量都能被另一方的场景反驳,讨论就永远停在感受上。
二、把感受换成三条线
我们最后定了一个很粗的预算:三条线,写进上线前的检查表。数值都是约数,取的是「中端机加 4G 模拟」这个偏保守的场景,不是实验室里的最好成绩。
| 指标 | 口径 | 预算线 | 测法 |
|---|---|---|---|
| 首屏可交互时间 | 从点击打开到首屏主要按钮可点,冷启动,缓存为空 | 约 3 秒内 | 固定一台中端机,把网络限速到 4G,连续测五次取中间值 |
| 首屏资源体积 | 首屏渲染必需的文字、样式、脚本和图片,压缩之后 | 约 1MB 内 | 看构建产物里的首屏依赖,不含懒加载部分 |
| 首屏请求数 | 首屏渲染期间发起的网络请求总数 | 约 30 个内 | 清空网络面板后刷新一次,数首屏完成前的请求 |
三条线里没有一条是精确的。3 秒不是 3000 毫秒的承诺,1MB 也不卡到 KB。但我们需要的不是一个能写进合同的数字,而是一把所有人都在用的尺子。
三、为什么粗颗粒够用
定预算的时候,有人提议做得更细:分页面、分机型、分网络制式。我算了一下成本:每增加一个维度,测量和解释的成本都要翻倍,收益只是把判断从「大概」变成「比较准」。
对我们这种规模的页面来说,争论的成本高于精度的收益。两周的会已经证明了这一点:我们缺的不是更精确的数字,而是能结束争论的一条线。
粗颗粒还有一个好处:它容易被记住。三条线,开发在提交前自己就能对一遍,不需要打开一份几十页的规范。
四、测量口径三条
预算如果不配口径,就会被各自的场景解释掉。所以我们同时定了三条测量规则。
- 固定设备档位。只用一台几年前的中端机,不换机,也不另外清理变量。不测最新的旗舰,也不测已经淘汰的机型。
- 固定网络。统一用开发者工具里的 4G 模拟,不用办公室 Wi-Fi,也不用「我家网很快」。
- 固定首屏定义。首屏指主要内容可见且主要操作可点,不是「白屏结束」,也不是「所有图片加载完」。这个定义要写下来,否则每个人心里的首屏都不一样。
这三条看起来笨,但它们的作用是让两次测量可比。可比比精确重要:一个偏保守但稳定的数,胜过一组各自漂亮、却没法互相比较的数。
五、超预算时先砍什么
预算真正的用处,是在超线那一刻给出顺序,而不是给出一个分数。我们的顺序是这样。
- 推迟非首屏脚本。统计、埋点、客服组件,能延后就延后,首屏并不需要它们。
- 裁剪图片和字体。先压图片尺寸和格式,再考虑字体子集化。这两项通常收益大、改动小。
- 减少第三方脚本。每引入一个外部脚本,都要问一句它是否必须在首屏加载。
- 砍功能。前三条都做完还超线,就和需求方一起决定首屏先不放哪个模块。这一条最难,但必须有人做决定。
这个顺序的意义是:先动不影响功能的部分,最后才动功能。反过来的话,讨论会立刻变成「这个功能能不能不要」,并且很难有结论。
六、踩过的三个坑
第一个坑是只测一次。第一次测出来略低于预算线,大家松了口气,上线后仍然收到一堆说慢的反馈。后来固定测五次取中间值,才发现单次波动很大。
第二个坑是只看总分。有个工具给了一个分数,分数不低,但首屏那个关键按钮仍然要等很久。总分是平均出来的,用户感受到的却是最慢的那一步。
第三个坑是把预算做成考核。有一阵我们把三条线挂到个人考核上,结果大家开始挑好测的场景、挑快的机器。预算一旦变成考核,数据就会变成争取资源的材料,而不是判断依据。
七、三个月之后
三个月后再看,变化不是页面变得多快,而是上线前多了一张检查表:三条线各测一次,超线就按顺序处理,处理完再测。讨论从「感觉慢不慢」变成了「哪条线超了、先砍哪个」。
这张表也让我对性能优化的看法变了:它不是一次运动,而是每次上线都要过的关口。关口不需要很精细,但必须每次都过。
现在如果有人跟我说这个页面有点慢,我的第一句话不是「我看看」,而是「在什么设备、什么网络、什么时候打开」。问完这三句,争论通常已经结束了一半。
本文为个人经验与观点,不代表任何机构。