可直接用PerformanceObserver捕获INP指标,需监听event类型、启用buffered:true并早期注册,entry.duration为交互到下一帧总耗时,取所有有效duration的第98百分位值,再结合longtask与performance.mark定位卡顿根源。

不能直接测量“HTML 渲染引擎”的交互响应延迟——浏览器没有暴露这个层级的指标,但你可以用 PerformanceObserver 捕获真实用户交互到下一帧渲染的端到端耗时,即 INP(Interaction to Next Paint),它是当前唯一被 Chrome 官方采纳、反映 UI 响应延迟的核心指标。
监听 event 类型获取原始交互耗时数据
INP 不是单个 API 调用就能拿到的值,它依赖 PerformanceEventTiming 条目,必须通过监听 event 类型来收集原始数据:
- 必须在
<head>早期执行,且启用buffered: true,否则会漏掉首屏交互(如用户在 JS 加载完成前就点了按钮) - 判断支持性不能只看
'PerformanceObserver' in window,还要检查PerformanceObserver.supportedEntryTypes?.includes('event') -
entry.duration是关键字段:它等于entry.processingEnd - entry.startTime,即从用户操作开始,到浏览器完成本次渲染帧的总时间 - 过滤掉无效条目:
entry.duration 或 <code>entry.name === 'pointermove'(大量冗余)可忽略
为什么不能直接用 first-input?
first-input 类型已被废弃(Chrome 113+ 默认不触发),且它只捕获首次交互,无法反映页面生命周期中反复出现的卡顿。INP 的价值正在于覆盖全部交互:
-
first-input只上报一次,event类型持续上报所有点击、敲击、空格键等有效交互 -
entry.name可区分行为类型:'click'、'keydown'、'pointerdown',便于按场景归因 - 若只监听
first-input,你会错过 SPA 路由切换后新组件的响应问题,比如搜索框第二次输入延迟飙升 - 现代框架(React/Vue)常复用 DOM 节点,
event条目能准确绑定到具体元素的entry.target(需配合performance.setResourceTimingBufferSize(200)提升捕获率)
聚合计算 INP 值时容易踩的坑
浏览器不会给你一个现成的 inp 字段,你得自己维护候选集并取第 98 百分位,但实操中几个细节决定结果是否可信:
立即学习“前端免费学习笔记(深入)”;
- 数组不能无限增长:建议上限设为 100~200 个,超出后用
shift()弹出最旧条目,避免内存泄漏 - 排序必须用
Array.prototype.sort((a, b) => a - b),JavaScript 默认字符串排序会导致100排在20前面 - 取第 98 百分位要向下取整:
Math.floor(candidates.length * 0.98),不是Math.round或Math.ceil - 别在每次回调里都重算:只在页面卸载前(
beforeunload)或每 30 秒定时计算一次,否则频繁排序拖慢主线程 - 注意跨域 iframe:其
event条目可能缺失entry.target,但entry.duration仍有效,不要因此丢弃整条
真正难的不是拿到数字,而是把高 duration 条目和具体代码路径对齐——PerformanceObserver 不提供调用栈,你得靠 longtask 时间戳 + performance.mark() 打点 + Chrome DevTools 的 Event Log 面板三者时间轴叠加,才能定位到某次 click 后紧跟着的 142ms 长任务到底来自哪个 useEffect 或 computed 函数。


















