了解如何优化网站的 Interaction to Next Paint。
发布时间:2023 年 5 月 19 日;上次更新时间:2025 年 9 月 9 日
Interaction to Next Paint (INP) 是一项稳定的核心网页指标,用于通过观测用户访问网页期间发生的所有符合条件的互动的延迟时间,评估网页对用户互动的总体响应情况。最终 INP 值是观测到的最长互动时间(有时会忽略离群值)。
为了提供良好的用户体验,网站应尽力将 Interaction to Next Paint 控制在 200 毫秒以内。为了让大多数用户都能达到此目标值,一个不错的衡量阈值是按移动设备和桌面设备细分的网页加载时间的第 75 个百分位数。
根据网站的不同,互动可能很少或没有,例如,网页上大多是文字和图片,很少或没有互动元素。或者,对于文本编辑器或游戏等网站,互动次数可能达到数百次甚至数千次。无论哪种情况,如果 INP 较高,用户体验都会受到影响。
虽然改进 INP 需要时间和精力,但回报是更好的用户体验。在本指南中,我们将探讨如何改进 INP。
找出导致 INP 较差的原因
在修复互动缓慢问题之前,您需要先获取数据,以了解网站的 INP 是较差还是需要改进。获得这些信息后,您就可以进入实验室,开始诊断缓慢的互动,并逐步找到解决方案。
在现场查找缓慢的互动
理想情况下,您应先从实地数据着手,开始优化 INP。在最佳情况下,实时用户监控 (RUM) 提供商提供的实测数据不仅会提供网页的 INP 值,还会提供相关数据,突出显示导致 INP 值的具体互动、互动是在网页加载期间还是之后发生的、互动类型(点击、按键或点按)以及其他有价值的信息。
如果您不依赖 RUM 提供商来获取实测数据,INP 实测数据指南建议使用 PageSpeed Insights 查看 Chrome 用户体验报告 (CrUX) 数据,以帮助填补空白。CrUX 是核心网页指标计划的官方数据集,可提供数百万个网站(包括 INP)的指标高级摘要。不过,CrUX 通常不会提供您从 RUM 提供商处获得的背景数据,因此无法帮助您分析问题。因此,我们仍然建议网站尽可能使用 RUM 提供商,或实现自己的 RUM 解决方案,以补充 CrUX 中提供的内容。
在实验室中诊断缓慢的互动
理想情况下,当现场数据表明存在互动缓慢的情况时,您就可以开始在实验室中进行测试了。在没有实地数据的情况下,有一些策略可用于在实验室中识别缓慢的互动。此类策略包括遵循常见用户流程并测试沿途的互动,以及在加载期间(主线程通常最繁忙)与网页互动,以便在用户体验的关键部分识别缓慢的互动。
优化互动
确定缓慢的互动并能在实验室中手动重现该互动后,下一步就是对其进行优化。
互动可分为三个子部分:
- 输入延迟时间,从用户开始与网页互动时算起,到互动事件回调开始运行时结束。
- 处理时长,即事件回调运行到完成所需的时间。
- 呈现延迟时间,即浏览器呈现包含互动视觉效果的下一个帧所用的时间。
这三个子部分的总和就是总互动延迟时间。互动的每个子部分都会为总互动延迟时间贡献一定的时间,因此了解如何优化互动的每个部分,使其尽可能短时间运行非常重要。
识别并缩短输入延迟时间
当用户与网页互动时,该互动的第一个部分是输入延迟时间。根据网页上的其他活动,输入延迟可能会相当长。这可能是由于主线程上发生的活动(可能是由于脚本加载、解析和编译)、提取处理、计时器函数,甚至由于快速连续发生且相互重叠的其他互动所致。
无论互动的输入延迟来自何处,您都需要将输入延迟降至最低,以便互动能够尽快开始运行事件回调。
启动期间脚本评估与长时间运行任务之间的关系
网页生命周期中交互性的一个关键方面是在启动期间。网页加载时,会先进行渲染,但请务必注意,网页已渲染并不表示网页已完成加载。根据网页完全正常运行所需的资源数量,用户可能会在网页仍在加载时尝试与网页互动。
在网页加载期间,脚本评估可能会延长互动的输入延迟时间。从网络中提取 JavaScript 文件后,浏览器在运行该 JavaScript 之前仍需执行一些工作;这些工作包括解析脚本以检查其语法是否有效、将其编译为字节码,然后最终执行它。
根据脚本的大小,这项工作可能会在主线程上引入长时间运行的任务,从而延迟浏览器对其他用户互动的响应。为了让网页在加载期间对用户输入保持响应,请务必了解如何降低网页加载期间出现长时间任务的可能性,以便网页保持流畅。
优化事件回调
输入延迟只是 INP 衡量指标的第一部分。您还需要确保响应用户互动的事件回调能够尽快完成。
经常让出主线程
优化事件回调的最佳一般性建议是在其中尽可能少地执行工作。不过,您的互动逻辑可能很复杂,您可能只能略微减少其工作量。
如果您发现自己的网站存在这种情况,接下来可以尝试将事件回调中的工作拆分为单独的任务。这样可以防止集体工作变成阻塞主线程的长任务,从而使原本需要等待主线程的其他互动能够更快地运行。
setTimeout
是一种分解任务的方式,因为传递给它的回调会在新任务中运行。您可以单独使用 setTimeout
,也可以将其使用抽象为单独的函数,以实现更符合人体工程学的生成。
无差别地让出资源比根本不让出资源要好,但还有一种更细致的方式可以向主线程让出资源,即仅在更新用户界面的事件回调之后立即让出资源,以便渲染逻辑能够更快地运行。
让步以允许更早地进行渲染工作
一种更高级的让步技术涉及在事件回调中构建代码,以将运行的内容限制为仅用于为下一帧应用视觉更新所需的逻辑。其他所有内容都可以推迟到后续任务中处理。这不仅能让回调保持轻量级和灵活性,还能通过不允许视觉更新阻塞事件回调代码来缩短互动渲染时间。
例如,假设有一个富文本编辑器,可在您输入文字时设置文字格式,同时还会根据您输入的内容更新界面的其他方面(例如字数统计、突出显示拼写错误和其他重要的视觉反馈)。此外,应用可能还需要保存您撰写的内容,以便您在离开后返回时不会丢失任何工作。
在此示例中,需要根据用户输入的字符执行以下四项操作。不过,只有第一项需要在呈现下一帧之前完成。
- 使用用户输入的文字更新文本框,并应用任何所需的格式。
- 更新显示当前字数的界面部分。
- 运行逻辑以检查拼写错误。
- 保存最近的更改(本地或远程数据库)。
实现此目的的代码可能如下所示:
textBox.addEventListener('input', (inputEvent) => {
// Update the UI immediately, so the changes the user made
// are visible as soon as the next frame is presented.
updateTextBox(inputEvent);
// Use `setTimeout` to defer all other work until at least the next
// frame by queuing a task in a `requestAnimationFrame()` callback.
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
以下可视化图表显示了将所有非关键更新延迟到下一帧之后可以如何缩短处理时长,从而缩短整体互动延迟时间。

虽然在之前的代码示例中,在 requestAnimationFrame()
调用中使用 setTimeout()
确实有点深奥,但它是一种有效的方法,可在所有浏览器中防止非关键代码阻塞下一帧。
避免布局抖动
布局抖动(有时称为强制同步布局)是一种渲染性能问题,其中布局是同步发生的。当您在 JavaScript 中更新样式,然后在同一任务中读取这些样式时,就会发生布局抖动。JavaScript 中有很多属性可能会导致布局抖动。

布局抖动是一种性能瓶颈,因为通过更新样式,然后在 JavaScript 中立即请求这些样式的值,浏览器会被迫执行同步布局工作,而本来可以在事件回调完成运行后等待稍后异步执行。
最大限度缩短展示延迟时间
互动的呈现延迟时间是指从互动事件回调完成运行时开始,到浏览器能够绘制显示相应视觉变化结果的下一帧时为止的时间。
最大限度地减小 DOM 大小
当网页的 DOM 较小时,渲染工作通常会很快完成。不过,当 DOM 非常大时,渲染工作往往会随着 DOM 大小的增加而增加。渲染工作与 DOM 大小之间的关系并非线性关系,但大型 DOM 的渲染工作量确实比小型 DOM 的渲染工作量大。在以下两种情况下,大型 DOM 会带来问题:
- 在初始网页渲染期间,如果 DOM 较大,则需要大量工作才能渲染网页的初始状态。
- 在响应用户互动时,大型 DOM 可能会导致渲染更新非常耗费资源,从而增加浏览器呈现下一帧所需的时间。
请注意,在某些情况下,无法大幅减少大型 DOM。虽然您可以采取一些方法来减小 DOM 大小,例如扁平化 DOM 或在用户互动期间添加到 DOM 以保持初始 DOM 大小较小,但这些技巧可能只能在一定程度上发挥作用。
使用 content-visibility
延迟渲染屏幕外的元素
限制网页加载期间的渲染工作量和响应用户互动的渲染工作量的一种方法是依赖 CSS content-visibility
属性,该属性实际上相当于在元素接近视口时延迟渲染元素。虽然有效使用 content-visibility
可能需要一些实践,但如果能缩短渲染时间,从而改善网页的 INP,那么就值得一试。
了解使用 JavaScript 渲染 HTML 时的性能开销
只要有 HTML,就会有 HTML 解析。浏览器将 HTML 解析为 DOM 后,必须对其应用样式、执行布局计算,然后渲染该布局。这是不可避免的费用,但呈现 HTML 的方式很重要。
当服务器发送 HTML 时,它会以流的形式到达浏览器。流式传输是指服务器的 HTML 响应以块的形式到达。浏览器会优化其处理流的方式,即在流的各个块到达时对其进行增量解析,并逐位呈现。这是一种性能优化,因为浏览器会在网页加载期间定期自动隐式让步,而您无需为此付出任何代价。
虽然首次访问任何网站时总是会涉及一些 HTML,但一种常见的方法是从最少的初始 HTML 开始,然后使用 JavaScript 填充内容区域。对该内容区域的后续更新也是因用户互动而发生的。这通常称为单页应用 (SPA) 模型。此模式的一个缺点是,通过在客户端使用 JavaScript 呈现 HTML,您不仅需要支付 JavaScript 处理费用来创建该 HTML,而且浏览器在完成 HTML 的解析和呈现之前不会产生任何输出。
不过,请务必注意,即使是不是 SPA 的网站,也可能会因互动而涉及一定程度的通过 JavaScript 进行的 HTML 渲染。一般来说,只要您不在客户端上呈现大量 HTML,这都没问题,否则可能会延迟下一帧的呈现。不过,您需要了解这种在浏览器中呈现 HTML 的方法对性能的影响,以及如果您使用 JavaScript 呈现大量 HTML,这种方法可能会如何影响网站对用户输入的响应速度。
总结
改进网站的 INP 是一个迭代过程。当您修复了实际环境中的缓慢互动后,很有可能(尤其是当您的网站提供大量互动时)会开始发现其他缓慢互动,您也需要对其进行优化。
提高 INP 的关键在于坚持不懈。随着时间的推移,您可以将网页的自适应能力提升到让用户满意的程度。很有可能的是,在为用户开发新功能时,您可能需要经历相同的流程来优化专门针对这些用户的互动。这需要时间和精力,但绝对值得。
主打图片来自 Unsplash,由 David Pisnoy 拍摄,并根据 Unsplash 许可进行了修改。