前端性能指标与测量(Performance API)
前端性能不能只看“页面什么时候加载完”。用户更关心的是:服务器什么时候响应、页面什么时候出现内容、主体内容什么时候可见、页面什么时候可以流畅交互,以及加载过程中是否发生跳动。
1. Core Web Vitals
Core Web Vitals 是 Google 用来衡量真实用户体验的一组核心指标。当前包括:
- LCP(Largest Contentful Paint):最大内容绘制,衡量加载性能。
- 良好:≤ 2.5s。
- 表示视口内最大的图片、文本块或视频封面等候选元素完成绘制的时间。
- INP(Interaction to Next Paint):交互到下次绘制,衡量交互响应性。
- 良好:≤ 200ms。
- 观察点击、触摸和键盘输入等交互,并用接近最慢的一次交互延迟代表页面响应性。
- INP 已经替代只关注首次交互的 FID。
- CLS(Cumulative Layout Shift):累积布局偏移,衡量视觉稳定性。
- 良好:≤ 0.1。
- 例如图片没有预留尺寸,加载后把下方内容突然推开,就可能产生布局偏移。
评估线上数据时,通常看页面访问数据的 第 75 百分位(P75) 是否达到“良好”标准。
Core Web Vitals 不等于首屏加载指标。LCP 与首屏加载直接相关;INP 关注交互响应;CLS 统计页面生命周期中的意外布局偏移。
2. 首屏加载还要关注哪些指标
一次页面加载可以拆成“服务端响应 → 首次可见 → 主体内容可见 → 可交互”几个阶段。
指标之间的关系
一般情况下可以粗略理解为:
这些事件并不保证严格按上述顺序发生。例如,异步数据可能让业务首屏完成时间晚于 load;用户也可能在 LCP 发生前就开始交互。
FCP 不等于首屏时间
- FCP 只表示第一个有效内容出现,可能只是标题或骨架屏。
- LCP 更接近“首屏主体出现”,但最大的元素不一定就是业务上的关键内容。
- 首屏时间 没有统一的浏览器原生定义,应根据业务确定关键模块,并在它们真正渲染完成时埋点。
因此,监控首屏体验时通常组合使用 TTFB + FCP + LCP + 自定义首屏时间,而不是只看某一个指标。
3. 测量方式
3.1 Performance API
PerformanceNavigationTiming 可以拆分导航过程中的 DNS、TCP、TLS、请求响应和 DOM 处理耗时。
需要注意:
responseStart - startTime是从本次导航开始计算的 TTFB,包含重定向和连接建立等阶段。responseStart - requestStart只表示请求发出后等待首字节的时间,不是完整 TTFB。- 使用了连接复用或缓存时,DNS、TCP、TLS 耗时可能为
0。
3.2 Paint Timing
通过 paint 类型可以获取 FP 和 FCP:
3.3 PerformanceObserver
PerformanceObserver 可以持续监听浏览器产生的性能条目。LCP 在页面加载过程中可能出现多个候选值,应保留最后一个有效候选值,并在页面隐藏时上报。
生产环境还要处理后台页面、往返缓存(bfcache)、页面提前关闭等边界情况,因此更推荐使用成熟的 web-vitals 库采集 Core Web Vitals。
3.4 web-vitals 库
3.5 自定义首屏时间
对于需要等待接口数据和图片渲染的页面,可以在首屏关键内容真正完成后打点:
自定义指标必须先明确:
- 哪些模块属于首屏关键内容;
- 骨架屏算“内容出现”还是只算占位;
- 图片加载失败时何时结束等待;
- 客户端路由切换是从点击、路由开始,还是数据请求开始计时。
4. 实验室数据与真实用户数据
- 实验室数据(Lab):在固定设备和网络条件下重复测试,例如 Lighthouse。适合开发阶段定位问题、对比优化前后结果。
- 真实用户数据(Field / RUM):采集真实用户设备、网络和交互产生的数据。适合判断线上用户的实际体验。
两者应结合使用:实验室数据负责复现和诊断,真实用户数据负责发现真实分布与长尾问题。线上统计建议按页面、设备、网络、地区等维度拆分,并关注 P75,而不只看平均值。
5. 常见面试题
Q:performance.now() 和 Date.now() 有什么区别?
Date.now()返回 Unix 时间戳,单位为毫秒,可能受系统时间调整影响。performance.now()返回相对于performance.timeOrigin的高精度时间,单调递增,不受系统时钟校准影响,更适合测量耗时。
performance.now()的单位仍然是毫秒,只是可以包含小数;出于安全和隐私考虑,浏览器可能降低其实际精度。
Q:白屏时间、FCP 和首屏时间有什么区别?
- 白屏时间:通常用 FP 或 FCP 近似,表示页面何时开始出现像素或有效内容。
- FCP:第一个有效内容完成绘制。
- 首屏时间:首屏关键内容完成展示,通常使用 LCP 或业务自定义指标衡量。
Q:如何优化 LCP?
先根据 LCP 的耗时组成定位瓶颈,再选择优化方式:
- 降低 TTFB:使用 CDN、页面缓存、SSR 流式输出,优化服务端查询和渲染。
- 尽早发现 LCP 资源:让关键图片出现在初始 HTML 中,必要时使用
preload,避免通过 JavaScript 延迟注入。 - 提高资源优先级:关键图片可以使用
fetchpriority="high",不要对首屏 LCP 图片使用懒加载。 - 减小资源体积:使用合适尺寸和格式的图片,开启压缩与缓存。
- 减少渲染延迟:内联少量关键 CSS,拆分长任务,减少阻塞渲染的 CSS 和同步 JavaScript。
Q:TBT 和 INP 有什么区别?
- TBT 统计加载阶段主线程长任务造成的阻塞,主要用于实验室测试,即使用户没有交互也能测量。
- INP 来自实际交互,衡量事件等待、事件处理和下一帧绘制的整体延迟,更适合表示真实用户的交互体验。
Q:为什么不能只看 DOMContentLoaded 或 load?
它们描述的是浏览器加载生命周期,而不是用户看到的内容:
- SPA 可能在
DOMContentLoaded后才请求并渲染首屏数据; load可能等待首屏之外的图片,也可能早于异步业务内容完成;- 页面即使已经触发
load,仍可能因为长任务而无法及时响应用户。
所以应优先使用以用户体验为中心的 FCP、LCP、INP、CLS,以及与业务匹配的自定义指标。

