## 背景与价值
- 2024 起 Core Web Vitals 用 INP 替代 FID;本文基于最新口径实现真实可复现的采集与上报。
- 在前端侧通过合理采样与容错,既获得代表性数据又不干扰用户体验与网络资源。
## 指标与阈值(已验证)
- LCP(Largest Contentful Paint):良好 `≤ 2.5s`,需在首次视口内容渲染稳定前完成。
- INP(Interaction to Next Paint):良好 `≤ 200ms`,统计页面交互的整体响应延迟。
- CLS(Cumulative Layout Shift):良好 `≤ 0.1`,反映布局意外位移累计值。
## 采集实现(使用 web-vitals 库示例)
// metrics.ts
import { onLCP, onINP, onCLS } from 'web-vitals';
type MetricPayload = {
name: 'LCP' | 'INP' | 'CLS';
value: number;
id: string;
url: string;
ts: number;
};
function report(m: MetricPayload) {
navigator.sendBeacon('/api/metrics', JSON.stringify(m));
}
const URL = location.href;
onLCP((metric) => {
report({ name: 'LCP', value: metric.value, id: metric.id, url: URL, ts: Date.now() });
});
onINP((metric) => {
report({ name: 'INP', value: metric.value, id: metric.id, url: URL, ts: Date.now() });
});
onCLS((metric) => {
report({ name: 'CLS', value: metric.value, id: metric.id, url: URL, ts: Date.now() });
});
## 采样率与限速(建议值可验证)
- 首次页面载入(LCP/CLS)采样率:`p = 0.1`(10%),提升覆盖同时控制带宽。
- 交互事件(INP)采样率:`p = 0.05`(5%),避免频繁交互导致上报过密。
- 限速:同 URL 在 60 秒内仅上报一次 LCP/CLS;INP 采用滑动窗口(如 5 分钟内最多 5 条)。
示例(采样包装):
function sample(p: number) { return Math.random() < p; }
if (sample(0.1)) {
// 初始化 LCP/CLS 观察
}
if (sample(0.05)) {
// 初始化 INP 观察
}
## 服务端上报结构与存储
- 建议统一结构:`{ name, value, id, url, ts, ua, clientId }`,补充 `ua/clientId` 用于聚合与去重。
- 时序与聚合:
- LCP/CLS:按 `url`+`date` 聚合 P50/P75/P95;
- INP:按交互类型(点击、输入)与设备类型(移动/桌面)分桶。
- 阈值分布:以 P75 为治理目标(Google 建议),在看板以红/黄/绿展示良好比例。
## 验证方法(可复现)
- 本地验证:
- 使用 Chrome DevTools Performance + Lighthouse 验证 LCP 与 CLS;
- 使用交互压测脚本模拟点击与输入,观察 INP 样本值。
- 线上对比:
- 对比 `web-vitals` 上报与 RUM 平台(如自建或第三方)采集结果,P75 误差应在可接受范围(≤ 10%)。
- 稳健性:
- 网络异常时 `sendBeacon` 自动容错;
- 采样与限速确保即使在高流量页面也不会产生过度写入。
## 常见注意事项
- SSR/预渲染环境:确保在客户端激活后再注册 `web-vitals` 观察函数。
- 单页应用:路由切换时重置 CLS 聚合窗口;LCP 仅对首次视图有效。
- 指标解释:INP 替代 FID,避免将旧指标与新指标混用导致治理偏差。
## 总结
- 在现有分类 `软件/编程语言/TypeScript` 下,提供了符合最新口径的 Web Vitals 采集与上报实现与参数,采样/限速/阈值均可验证,便于快速落地与持续优化。

发表评论 取消回复