必须用Event Timing API测INP,因其唯一提供processingStart字段,可精确计算用户交互到下一帧绘制的延迟(INP=processingStart−startTime),支撑全生命周期第98百分位最差响应统计,且需在<head>中注册并启用buffered:true才能捕获首屏交互。

页面响应性监测的核心,是准确捕获用户真实感知到的卡顿——不是代码执行多久,而是用户点下去后,界面何时真正动起来。Event Timing API 是目前唯一能直接支撑这一目标的原生机制,尤其在 INP 成为新版核心指标后,它已从“可选工具”变为“必用基础设施”。
为什么必须用 Event Timing API 测 INP
INP 不再只看首次点击,而是统计整个页面生命周期中所有交互里最差的一次响应延迟(第98百分位或最大值),定义为:用户触发事件(如 click)→ 浏览器开始执行回调 → 下一帧像素完成绘制。这个完整链条中,最关键又最难捕获的环节,就是“浏览器真正开始处理事件”的时刻(processingStart)。只有 Event Timing API 提供该字段,且与 startTime 相减,才得到标准 INP 值。
- performance.getEntriesByName('first-input') 返回的 duration 仅是回调函数内部执行耗时,常为 0 或极小值,完全掩盖主线程排队阻塞;
- 它只对首个 click/keydown/mousedown/touchstart 生效,无法覆盖后续所有交互,更无法支撑 INP 的“全生命周期最差值”逻辑;
- Chrome 69+、Edge 79+、Firefox 105+ 支持 event 类型 PerformanceEntry,但需主动启用 observer,否则无数据。
正确接入 Event Timing API 的关键配置
不是简单调用 API 就能拿到有效数据,漏掉任一配置都可能导致错过关键事件或数据失真:
- 在 <head> 中尽早注册 PerformanceObserver,监听 type: 'event',不能等 DOMContentLoaded 再初始化;
- 必须设置 buffered: true,否则页面加载完成前发生的交互(比如快速点击加载中的按钮)不会被缓存上报;
- 过滤 entry.entryType === 'event' 即可,无需混用 first-input;entry.name 是事件类型(如 'click'),entry.startTime 和 entry.processingStart 是计算基础;
- INP = entry.processingStart - entry.startTime,该值可能为 0(无排队),也可能达 300ms+(主线程严重阻塞)。
结合 Long Task API 定位阻塞根源
INP 高通常意味着主线程被长时间占用。Event Timing API 告诉你“卡了”,Long Task API 告诉你“被谁卡的”:
- 当 PerformanceLongTaskTiming 报告执行超 50ms 的任务时,说明该 task 很可能挤占了用户交互的调度时机;
- 配合 TaskAttributionTiming,可定位长任务来自哪个 iframe、script 标签或资源(containerSrc/containerId);
- 典型场景:一个未拆分的大型 JS 包在首屏解析时阻塞主线程,导致后续所有点击延迟升高,INP 值随之恶化。
日常监控与优化闭环建议
把 API 数据转化为可行动的优化项,需要结构化处理:
- 按页面路径聚合 INP 分布,识别高延迟页面(如编辑页、表单页);
- 将高 INP 事件与对应 Long Task 关联,确认是否由某段同步渲染逻辑、未节流的 resize 监听器或大型 canvas 绘制引起;
- 对强交互场景(如绘图、拖拽),优先采用 requestAnimationFrame 调度、Web Worker 卸载计算、或事件委托减少监听器数量;
- 避免在事件回调中执行 DOM 批量操作或重排重绘,改用 documentFragment 或 CSS transform 触发合成层。

















