INP 高,八成是主线程被长任务占住了。今年 9 月我们给 7 个软件站查过 INP,四类来源能解释其中 6 个:框架水合、输入处理器里的同步计算、第三方脚本抢线程、大列表一次性渲染。定位方法不复杂,打开 Performance 面板录一段真实操作,看 Interactions 和长任务轨道。
先把概念说清楚。INP 是 Interaction to Next Paint,2024 年 3 月正式替代 FID 成为 Core Web Vitals 的交互指标。它算的是用户每次点击、按键到界面画出下一帧的延迟,取整段会话里偏差最大的那次。FID 只算第一次输入的延迟,所以有些站 FID 一直很好看,换成 INP 立刻露馅。
第一类:框架水合
Next.js、Nuxt 这类站,HTML 出来了,JS 还没执行完,这段时间用户点任何东西都没反应。一个开发者工具站首屏水合占了 1.2 秒,用户在这段时间点了三次导航,INP 直接记了 780 毫秒。
查法:Performance 面板里找 hydrate 或者 long task,看它和用户首次点击的时间关系。改法不是优化水合本身,而是让首屏不依赖 JS——导航用原生链接,首屏内容服务端渲染,交互组件按需加载。
第二类:输入处理器里的同步计算
筛选、搜索、表单校验是重灾区。一个 B2B 后台的筛选器,每次点击同步算 1200 行数据的匹配,主线程卡 300 毫秒。用户连续点两下,感受就是卡死。
改法:把计算挪出事件处理器,用 requestAnimationFrame 或 startTransition 分帧;列表超过 200 行就上虚拟滚动。这类改动通常能砍掉一半的 INP。
第三类:第三方脚本抢主线程
热力图、AB 测试、客服组件,都喜欢在用户第一次交互时上报。我们见过一个站,点击后 180 毫秒内跑了 4 个第三方回调。查法是 Performance 面板里看长任务下面挂的脚本 URL,一眼能认出是谁。
第四类:大列表和复杂 DOM
一次渲染 500 个 DOM 节点,浏览器光做样式计算就要 100 多毫秒。文档页的侧边目录、定价页的对比表都是高发区。改法是分页、虚拟滚动、content-visibility。
查 INP 的顺序
先看 RUM 的 P75 和 P95,差距大说明问题集中在少数交互上,找到那个元素比全局优化划算。再去实验室复现,最后才动手改。我们一般先修 P95 最差的那个交互,因为它往往和其他问题同根。
怎么归因到具体元素
实验室只能看到"主线程卡了多久",看不到"用户点了哪个按钮"。要归因到元素,得在代码里埋一条 Interaction 记录:用 PerformanceObserver 监听 event 和 first-input,把 duration 超过 200 毫秒的交互连同比元素信息和页面路径一起上报。我们给客户搭的版本一天收上来十几万条,按页面聚合,最差的那个页面和按钮十分钟内就能锁定。
这一条比分数本身有用。分数只告诉你"差",归因告诉你"改哪里"。
移动端是重灾区
同一个站,桌面端 INP 120 毫秒、移动端 380 毫秒,在我们查过的站里是常态。中低端安卓机的单核性能只有开发机的五分之一,脚本解析和执行的时间都要乘上去。所以 INP 的验收一定要看移动端,尤其是国内安卓机型的分布。
还有一条边界:INP 低于 200 毫秒就别折腾了。这类改动风险高、验收难,收益已经不明显,把时间花在内容和转化上更划算。
元析智能
为软件公司做 SEO 和 GEO 优化