很多团队做性能优化全靠"感觉":用户反馈卡,就打开本地 DevTools 跑一次 Lighthouse,分数好看就认为优化完成。可本地千兆网络、高配电脑跑出来的数据,和真实用户在地铁里用千元机打开页面的体验完全是两回事。真正能指导优化的,是一套采集真实用户指标(RUM)的前端性能监控体系。本文拆解如何用 Web Vitals 标准采集核心指标、如何可靠上报、以及怎么搭出有意义的异常告警。
一、先统一指标:盯哪几个数
业界已有成熟标准,不必自造。核心是三个 Web Vitals 指标,分别对应加载、交互、视觉稳定:
- LCP(最大内容绘制):主要内容渲染出来的时间,衡量"加载快不快",良好阈值 2.5 秒内;
- INP(交互到下一次绘制):用户点击后页面响应的延迟,衡量"操作跟不跟手",良好阈值 200 毫秒内;
- CLS(累积布局偏移):页面加载过程中元素意外位移的程度,衡量"稳不稳",良好阈值 0.1 以内。
再辅以 FP/FCP(首次绘制/首次内容绘制)、TTFB(首字节时间)、资源加载耗时,就能定位问题到底出在网络、服务端还是前端渲染。
二、采集:用标准 API,不要自己算偏移
这些指标浏览器提供了原生入口,社区也有封装好的库,直接采集即可,不要手动用 performance.now() 去拼算,边界情况极多。
import {
onLCP, onINP, onCLS, onFCP, onTTFB } from "web-vitals";
function send(metric) {
const payload = {
name: metric.name, // LCP / INP / CLS ...
value: Math.round(metric.value * 100) / 100,
rating: metric.rating, // good / needs-improvement / poor
id: metric.id,
page: location.pathname,
ts: Date.now()
};
beaconReport(payload);
}
onLCP(send); onINP(send); onCLS(send); onFCP(send); onTTFB(send);
采集时几个关键点:
- 指标是"页面生命周期结束"才最终定值的,比如 LCP 可能在加载过程中不断变化、CLS 要累积到页面卸载,因此要在
visibilitychange变为隐藏时补报最终值; - SPA 路由切换要手动打点,Web Vitals 默认按文档加载统计,单页应用切路由不会自动重置,需要在路由钩子里记录自定义渲染耗时;
- 带上分维度字段:页面路径、设备类型、网络类型、地区、App 版本,否则平均值会掩盖问题。
三、上报:用 sendBeacon,不阻塞、不丢失
性能数据不能因为上报本身拖慢页面,也不能在页面关闭时丢包。优先用 navigator.sendBeacon,它由浏览器调度、异步发出、不阻塞卸载:
function beaconReport(data) {
const body = JSON.stringify(data);
if (navigator.sendBeacon) {
navigator.sendBeacon("/collect/perf", new Blob([body], {
type: "application/json" }));
} else {
fetch("/collect/perf", {
method: "POST", body, keepalive: true });
}
}
工程上还要做两件事:一是合并上报,把一整次访问的多条指标攒起来、在页面隐藏或空闲时批量发送,降低请求数;二是采样,高流量站点不必全量上报,按比例采样即可,但慢指标(rating 为 poor)建议 100% 保留,因为它们才是优化目标。
四、聚合:别只看平均值
平均值最容易骗人:一半用户秒开、一半用户卡 8 秒,平均可能还是"良好"。聚合时重点看分位数:
- P75:Web Vitals 官方建议用第 75 百分位判断页面是否达标,即 75% 的用户体验良好才算良好;
- 按维度下钻:先看整体 P75,再按页面、设备、地区拆分,问题往往集中在某类低端机或某个弱网地区;
- 看分布而非单点:用直方图观察 LCP 落在各区间的占比变化,比单个数字更能反映优化效果。
五、告警:设阈值、看突变、防告警疲劳
告警不是"超过一个数就响",那样要么漏掉缓慢恶化、要么天天误报。推荐三类规则组合:
- 阈值告警:某页面 LCP P75 连续一段时间超过 2.5 秒,说明常态不达标;
- 突变告警:相比上周同时段,错误率或慢指标占比环比上涨超过设定比例,通常对应一次发版引入的回归;
- 可用性兜底:上报量本身骤降,往往是采集 SDK 挂了或页面白屏,属于监控的监控。
阈值要按页面重要程度分级,核心转化页面从紧,边缘页面从宽,避免告警过多导致没人看。
六、踩坑清单
- 只测本地不上真实用户数据:实验室数据无法代表真实体验,RUM 不可替代;
- 自己手算 Web Vitals:边界情况多,直接用官方库;
- 用 ajax 同步上报:阻塞页面、关闭时丢包,应用 sendBeacon;
- 只看平均值:被均值掩盖的长尾差体验才是优化重点,要看 P75 和分布;
- SPA 不处理路由切换:单页应用只采到首次加载,后续页面全是盲区;
- 全量上报不采样:高流量下白白增加服务端成本,慢请求却没重点保留;
- 告警只设固定阈值:漏掉缓慢恶化和发版突变,要阈值 + 环比组合。
七、工程落地建议
自建这套体系的工作量集中在采集 SDK、接收管道、聚合查询和告警平台四部分。如果站点基于成型平台搭建(如乔拓云企业网站),基础的访问统计、性能与来源数据通常已由平台内置看板提供,中小团队可先用内置数据定位明显问题,确有精细化诉求时再接入自研或第三方 RUM;自研站点则建议先把 Web Vitals 采集和 sendBeacon 上报跑通,再逐步补分位数聚合与告警,避免一上来追求大而全。
八、上线前复盘清单
- 是否采集 LCP/INP/CLS 并在页面隐藏时补报最终值;
- SPA 路由切换是否有自定义渲染打点;
- 上报是否用 sendBeacon、是否做了合并与采样;
- 是否带页面、设备、网络、版本等分维度字段;
- 看板是否以 P75 和分布为主、而非只看平均值;
- 告警是否覆盖阈值、环比突变、上报量骤降三类。
结语
性能优化的前提是可度量。用 Web Vitals 统一语言、用 RUM 还原真实体验、用分位数代替平均值、用组合告警盯住回归,一套轻量但完整的监控体系就能让优化从"凭感觉"变成"看数据"。当每一次改动都能在真实用户的指标曲线上看到效果,性能工作才算真正形成了闭环。