直接用performanceobserver捕获inp可行,但需组合监听event类型、聚合计算并关联longtask;须启用event timing api、早期注册observer、设置buffered:true及足够缓冲区,entry.duration为合成响应耗时,inp取所有交互duration的98分位值,需手动维护候选数组并定时统计。

直接用 PerformanceObserver 捕获 INP 是可行的,但不能靠监听单一事件“一键拿到”,它需要组合监听 event 类型 + 后续聚合计算,并结合 longtask 定位卡顿根源。
必须启用 Event Timing API 并监听 event 类型
INP 的原始数据来自 Event Timing API,浏览器只通过 type: 'event' 的 PerformanceEventTiming 条目暴露交互耗时。需在页面早期(如
内同步脚本)注册 observer,并开启 buffered: true,确保捕获注册前已发生的点击、键盘输入等交互:- 调用
performance.setResourceTimingBufferSize(200)提高缓冲容量 - 检查
'PerformanceEventTiming' in window再初始化 observer -
entry.duration表示该次交互从触发到下一帧渲染的总耗时,含输入延迟、处理延迟和呈现延迟
理解 duration 值的实际含义
entry.duration 是一个合成值,不拆解各阶段,但能快速反映响应健康度:
- ≥ 50ms:大概率存在长任务、强制同步布局或大量样式计算,需关注
- 单个高值 ≠ INP —— INP 是全生命周期中所有有效交互的第98百分位值,需累积数十次后统计
手动聚合近似 INP 并上报
官方 web-vitals 库正是这样实现的。你可轻量维护一个候选数组:
- 声明
const inpCandidates = [],每次收到entry.duration > 0就 push 进去 - 限制长度(如最多 100 个),避免内存持续增长
- 在
beforeunload或每 30 秒定时排序,取Math.floor(len * 0.98)索引位置的值作为当前 INP 估算
关联 longtask 定位 UI 卡顿根源
当发现某次交互 duration 显著偏高时,应同步检查是否伴随 longtask:
- 用另一个 PerformanceObserver 监听 longtask 类型(阈值建议 ≥100ms)
- 比对时间戳:若 longtask 的
startTime与高 duration 事件高度重叠,说明主线程被该任务阻塞 - 常见诱因包括:未节流的 resize/scroll 监听器、嵌套 layout thrashing、同步 DOM 查询+修改循环










