前端知库

讲一次你做过的性能优化,应该从哪些方面讲?

先说清楚优化前用什么指标、在什么环境下测出了什么问题,再按加载、渲染、交互分层说明做了哪些改动和为什么,最后用同样的方法测出优化后的数字,并说明怎样防止性能回退。重点是“有测量、有归因、有对比”,而不是罗列优化手段。

参考答案

本题是回答思路与示例,不对应某个官方规范。示例中的数字只用来演示怎样表达,讲自己的项目时请用真实数据。

简答

很多人回答这道题,会直接背一串手段:图片压缩、懒加载、代码分割、CDN、缓存。面试官听完不知道你到底做了哪件事、效果如何。好的回答应该像一次完整的排查:先测量,再归因,再改,再验证。

第一步说清楚问题和指标。用什么指标衡量,比如首屏用 LCP、交互用 INP、布局跳动用 CLS;在什么环境下测的,是实验室工具还是真实用户数据;优化前是多少。第二步说归因,怎样找到慢在哪里,比如 Lighthouse 报告、Performance 面板、资源瀑布图里看到了什么。

第三步说改动,按问题分层讲:加载慢是因为资源太大、请求太多还是服务器慢;渲染慢是因为阻塞资源、主线程任务太长还是布局抖动。每个改动都对应一个具体原因。第四步说结果,用同样的方法再测一次,给出前后对比。

最后补一句怎样防止回退,比如在 CI 里加性能预算、在监控里设告警。这一点能说明你考虑的是长期效果,而不是一次性的修补。

一个示例

问题:活动页在移动端首屏很慢,真实用户监测里 LCP 的 75 分位大约 4 秒,超过 2.5 秒的“良好”标准。

归因:看资源瀑布图,首屏大图是 1.2MB 的 PNG,而且要等 JS 执行完才开始请求,因为图片地址是脚本里动态插入的;主包 JS 有 800KB,里面包含了首屏用不到的图表库。

改动:大图改成 WebP 并按屏幕宽度提供多种尺寸,直接写在 HTML 里,加上 fetchpriority="high",让浏览器尽早下载;图表库改成进入可视区域后再动态导入;首屏以下的图片加上 loading="lazy"。

结果:LCP 的 75 分位降到 2 秒左右,首屏 JS 降到 300KB。

防回退:在构建流程里加了包体积检查,主包超过阈值就报警。

这个示例里,每一项改动都能对上一个归因:图片大,所以压缩;图片发现得晚,所以写进 HTML 并提高优先级;JS 大,所以拆分。面试官很可能追问其中某一项的原理,比如为什么首屏图片不能懒加载,相关内容见《懒加载为什么有时反而让首屏和首次交互变慢?》和《fetchpriority 能解决资源加载优先级问题吗?》。

实验室数据和真实用户数据要分开说

Lighthouse 这类工具在固定的设备和网络条件下测,结果稳定,适合对比改动前后;可是它只代表一种环境。真实用户监测收集的是用户实际访问时的数据,能反映不同机型和网络下的情况,但波动大,一般看 75 分位。讲优化效果时,最好说明数据来自哪里。只拿本地 Lighthouse 分数从 60 提到 90 当作成果,说服力不如真实用户数据的改善。两者怎样配合见《真实用户监测与实验室性能测试为什么要结合?》。

常见追问

你怎么确定是这个改动带来的提升,而不是别的因素?

改动尽量一个一个上,或者在实验室环境里用相同条件分别测;真实数据要对比同一时间段、同类用户。如果有条件,可以用灰度发布对比新旧版本。

优化有没有带来副作用?

要如实说。比如图片懒加载后,快速滚动时会短暂看到空白,于是加了占位色;代码拆分后多了请求,就对关键模块做了预加载。能说出副作用和对应处理,说明你真正做过。