INP 是什么?如何优化页面交互响应?
简化版
INP 衡量页面生命周期中大多数用户交互的响应延迟,良好标准是 P75 不超过 200ms。优化核心是减少输入延迟、处理耗时和呈现延迟:拆长任务、降低交互回调复杂度、避免同步布局和大范围渲染,并让用户尽早看到反馈。
详细版
一次交互从用户输入开始,到浏览器能绘制下一帧反馈结束。中间可能卡在三段:输入事件排队等待主线程、事件回调执行太久、回调后样式布局绘制太重。
优化不能只盯点击函数本身。大型列表重渲染、同步表单校验、第三方脚本长任务、布局读写交替、一次性 DOM 更新都会拉高 INP。应使用真实用户数据和 DevTools trace 找到具体交互、目标元素和最长任务。
常用手段包括把非关键工作延后、任务切片、Web Worker、乐观 UI、减少组件更新范围、虚拟列表、按帧合并高频事件,以及避免在交互回调里同步读取并写入大量布局。
完整版教学
一、INP 关注的是交互后的“下一次视觉反馈”
用户点击按钮后,如果 500ms 内页面没有任何响应,即使网络接口很快,用户也会觉得卡。INP 把一次交互拆成输入到下一次绘制的完整延迟,更贴近“点了有没有反应”。
当前 Core Web Vitals 口径中,INP ≤200ms 为良好,>500ms 为差,并按真实访问的第 75 百分位评价。它替代旧的 FID,是因为 FID 只看首次输入的输入延迟,而 INP 覆盖页面生命周期中更多交互。
记忆钩子:INP 不是接口耗时,而是“用户操作到页面画出反馈”的整段等待。
二、一次交互可以拆成三段
INP 由输入延迟、处理时间和呈现延迟组成。定位时要知道慢在排队、执行,还是执行后浏览器渲染太慢。
Interaction latency
= input delay
+ processing duration
+ presentation delay
| 分段 | 含义 | 常见根因 |
|---|---|---|
| input delay | 输入到事件回调开始 | 主线程被长任务占用 |
| processing duration | 回调执行耗时 | 重计算、同步校验、大状态更新 |
| presentation delay | 回调结束到下一帧绘制 | 布局、绘制、框架提交过重 |
比如用户点击发生在 1000ms,主线程到 1080ms 才空闲,回调跑 90ms,之后布局绘制 70ms,交互反馈约 80+90+70=240ms,已经超过良好阈值。
三、输入延迟通常来自主线程被占用
浏览器主线程正在执行一段 300ms 的 JS 时,新的点击事件只能排队。用户感知是“我已经点了,但页面没理我”。
0ms long task starts
120ms user click
300ms long task ends
301ms click handler starts
input delay ≈ 181ms
减少输入延迟要拆长任务。初始化、埋点、复杂 JSON 解析、首屏非关键组件渲染都可以分批执行;计算密集任务可移到 Worker。这里的目标不是所有任务都短,而是不要在用户可能交互的时段堵住主线程。
四、处理时间要从交互回调和状态更新下手
很多 INP 问题发生在事件回调内部:点击后同步过滤 5000 条数据、触发全局 store 更新、让整棵组件树重新渲染、立即执行复杂表单校验。
button.addEventListener('click', () => {
setOpen(true) // 先给即时反馈
setTimeout(runHeavyWork, 0) // 非关键工作延后
})
上面只是示意,真实项目可用任务切片、scheduler、框架的 transition 能力或 Worker。关键原则是先让用户看到最小反馈,再处理非关键工作;否则 30ms 的按钮状态更新可能被 300ms 的统计计算拖住。
五、呈现延迟常来自大范围布局和渲染
事件回调执行完,不代表用户马上看到反馈。浏览器还要计算样式、布局、绘制和合成。一次点击如果展开 2000 个 DOM 节点,或者让表格全部重排,呈现延迟会很高。
| 场景 | 风险 | 优化方向 |
|---|---|---|
| 大列表筛选 | 大量 DOM 更新 | 虚拟列表、分页、增量渲染 |
| 弹窗打开 | 布局和阴影绘制 | 预留结构、减少重绘区域 |
| 表单输入 | 全表单校验 | 字段级校验、延迟重校验 |
| 图表交互 | Canvas/DOM 重绘 | 降采样、Worker 计算 |
如果一次点击后框架提交 120ms,布局绘制 90ms,就算回调逻辑只有 20ms,INP 也可能达到 230ms。优化要看完整 trace,而不是只优化 handler 函数。
六、用真实数据定位具体交互
INP 是现场指标,不同用户点击的元素不同。监控要上报交互类型、目标元素摘要、耗时分段、页面模板、设备和 release。只看全站一个 INP 数字,很难知道该修哪个页面。
page=/checkout
interaction=click
target=.coupon-apply
inp=420ms
longTask=validateCouponForm 260ms
release=2026.07.29
实验室里可用 Chrome DevTools Performance 录制,查看 Interaction、Main thread 和 Rendering。现场数据负责发现“哪类用户在哪个 release 变差”,实验室负责解释“为什么变差”。
七、常见误区与追问
- 误区:INP 就是接口响应时间。 接口慢可能影响反馈,但 INP 衡量的是输入到下一次绘制的浏览器体验延迟。
- 误区:只要处理函数很短,INP 就一定好。 输入排队和回调后的布局绘制也会计入交互延迟。
- 误区:防抖所有点击能优化 INP。 防抖可能延迟反馈,交互应优先即时反馈,再延后非关键工作。
- 追问:INP 和 FID 有什么区别? FID 只看首次输入的输入延迟,INP 覆盖页面生命周期内的交互响应。
- 追问:为什么低端机 INP 更差? CPU 慢、主线程任务更长、布局绘制成本更高,同样代码耗时会放大。
- 追问:如何证明优化有效? 比较同页面同设备分群的 P75 INP、交互归因和 release 前后趋势。
八、加强记忆
INP 用“三段一闭环”记:输入延迟看主线程排队,处理时间看回调和框架更新,呈现延迟看布局绘制;优化时先给即时反馈,再拆长任务、缩小渲染范围、迁移重计算,并用现场 P75 和交互归因验证。