PerformanceObserver需早注册+开启buffered才能捕获首屏指标,按类型精准配置entryTypes,LCP/CLS/FCP/INP采集逻辑各异,自定义指标用mark/measurement,longtask监控卡顿需过滤伪任务并结合用户行为。

PerformanceObserver 是浏览器原生提供的异步性能监控机制,不是“装上就能用”的黑盒工具,而是需要按指标类型精准配置、在正确时机注册、并合理处理回调的系统性方案。关键不在监听本身,而在如何避免漏数据、不干扰主线程、能真实反映用户感知。
必须早注册 + 开 buffered 才不丢首屏数据
navigation、paint、largest-contentful-paint、layout-shift 这几类条目默认不缓存历史记录。如果 observer 在 window.onload 之后才 observe,首屏关键指标(如 FCP、LCP)基本收不到。
- 推荐做法:把初始化代码写在 <head> 内联 script 中,不加 defer/async,且在 document.readyState === 'loading' 阶段就执行
- 所有需捕获早期行为的类型(navigation/paint/LCP/CLS),observe 时必须显式传 buffered: true
- 不要写成
observer.observe({})—— 空配置等于没监听;必须指定 entryTypes 数组 或新版 type 字符串
按指标类型区别对待,不能套用同一套逻辑
LCP、CLS、FCP、INP 的采集方式完全不同,混用会导致数据失真或漏报。
-
LCP:监听
largest-contentful-paint类型,取entry.startTime,只触发一次,务必检查entry.element是否为预期主内容节点 -
CLS:监听
layout-shift类型,只累加entry.hadRecentInput === false的条目,每次回调都要叠加entry.value,不是取最后一次 -
FCP:无法监听,需在 load 后调用
performance.getEntriesByName('first-contentful-paint', 'paint')主动查;Safari 不稳定时可 fallback 到performance.timing近似估算 -
INP:替代已弃用的 FID,监听
event类型,过滤entry.interactionId > 0,遍历全部条目取最大entry.duration
自定义指标要靠 mark + measure 打点
想监控接口耗时、模块加载、动画帧等业务指标,不能只靠内置类型,得自己构造可追踪的 measure 条目。
- 先用
performance.mark('xxx-start')和performance.mark('xxx-end')标记时间点 - 再用
performance.measure('xxx-time', 'xxx-start', 'xxx-end')生成命名条目 - PerformanceObserver 监听
measure类型,通过entry.name匹配、entry.duration判断超时、entry.detail携带上下文(如用户 ID、API 路径) - 避免在回调里直接发请求;上报建议用
navigator.sendBeacon(),并做节流或队列聚合
监听 longtask 是定位卡顿最直接的方式
页面卡顿主因不是 FPS 掉帧,而是单个 JS 任务阻塞主线程超过 50ms。longtask 类型正是为此设计。
- 必须在 head 最早位置注册,否则错过首屏解析、渲染等关键长任务
- 关注连续性:3 秒内出现 ≥3 次
entry.duration > 50才需告警,单次不具代表性 - 过滤伪长任务:排除
entry.name === 'iframe'或 attribution 明确指向广告/统计 SDK 的条目 - 结合用户行为打点(如 click 前后 mark),能把长任务和具体操作场景对齐,大幅缩小排查范围


















