performanceobserver 可直接监听 lcp、cls 和 inp(替代已弃用的 fid),fcp 需在 load 后主动查询;所有监听必须在页面加载早期注册并设置 buffered: true,lcp 取 entry.starttime,cls 累加 hadrecentinput 为 false 的 layout-shift 值,inp 取所有交互中最大 duration。

可以直接用 PerformanceObserver 监听 LCP、CLS,FCP 需主动查表,FID 已被弃用,应改用 INP。所有监听必须在页面加载早期注册,并设置 buffered: true,否则会漏掉首屏关键数据。
监听 LCP:捕获最大内容绘制时间
LCP 只触发一次,代表用户视口内“主要内容”完成渲染的时刻。监听必须早于 load 事件,推荐放在 中执行:
- 观察类型为
'largest-contentful-paint',不能用'paint'或其他泛型 - 取值用
entry.startTime(单位毫秒,从 navigationStart 起算) - 务必设置
buffered: true,确保能收到页面加载过程中已发生的 LCP 条目 - 可选读取
entry.element判断是否为 banner、主图或标题等首屏核心节点
监听 CLS:累加所有无交互触发的布局偏移
CLS 是动态累积值,需持续监听并叠加所有符合条件的 layout-shift 条目:
- 观察类型为
'layout-shift' - 只累加
entry.hadRecentInput === false的条目,排除用户操作引起的偏移 - 每次回调中对
entry.value求和(不是取最后一次),初始值设为 0 - 建议在
visibilitychange事件触发且document.hidden === true时汇总上报,避免卸载前遗漏
获取 FCP:无法监听,需主动查询
FCP 不支持实时监听(Chrome 120+ 才实验性支持 paint 类型),稳妥做法是在 load 后主动读取:
- 调用
performance.getEntriesByName('first-contentful-paint', 'paint') - 取返回数组第 0 项的
startTime;若为空,说明尚未触发,可设 5s 超时兜底 - Safari 对
paint类型支持不一致,必要时 fallback 到performance.timing计算近似值
替换 FID:改用 INP 并取最差交互响应
FID 已于 2024 年被 Google 正式弃用,INP(Interaction to Next Paint)是当前标准交互指标:
- 观察类型为
'event',过滤出entry.interactionId > 0的条目 - INP 是所有有效交互中最大的
entry.duration(含输入处理 + 渲染延迟) - 不是首次值、也不是平均值,必须遍历全部条目后取最大
- 监听同样需在
document.readyState === 'loading'阶段就位,否则错过首屏点击










