优化网站 Interaction to Next Paint 的方法
发布日期: 2023年5月19日
最后更新: 2025年9月2日
Interaction to Next Paint(INP)是衡量网页响应性的核心 Web Vitals 指标之一。它通过监控页面访问期间所有关键交互的延迟,来评估页面对用户交互的整体响应能力。最终的 INP值是在监测期间耗时最长的交互(排除可能的异常值)。
为了提供优秀的用户体验,建议将网站的 INP 控制在 200 毫秒以下。为确保大多数用户都能达到目标,建议使用移动设备和桌面设备上页面加载的第 75 百分位数作为测量阈值。
INP 的阈值
某些网站可能交互较少或几乎没有交互,例如以文本和图像为主的页面。而对于文本编辑器或游戏类网站,则可能产生数百甚至数千次交互。但无论哪种情况,INP 过高都可能导致用户体验受损。
有关详细信息,请参阅 Interaction to Next Paint(INP)。
虽然优化 INP 需要投入时间和精力,但能够显著提升用户体验。本指南将详细介绍改善 INP 的具体方法。
识别 INP 低下的原因
要修复交互延迟,首先需要数据来判断网站的 INP 是否偏低,以及哪些方面需要改进。获取这些信息后,就可以在实验室环境中诊断缓慢的交互并寻找解决方案。
通过现场数据发现缓慢交互
理想情况下,INP 的优化应始于现场数据。真实用户监控(RUM)提供商的现场数据不仅包含页面的 INP 值,还提供关键上下文信息,例如导致高 INP 的具体交互、交互发生在页面加载期间还是之后、交互的类型(点击、按键、轻触)等。
更多信息请参阅:发现现场缓慢交互。
如果未使用 RUM 提供商收集现场数据,建议按照 INP 现场数据指南 使用 PageSpeed Insights 查看 Chrome 用户体验报告(CrUX)数据,以填补数据空白。CrUX 是 Core Web Vitals 计划的官方数据集,提供数百万网站(包括 INP)的指标概览。但需要注意的是,CrUX 通常无法提供 RUM 提供商所能提供的、有助于问题分析的详细上下文数据。因此,如果条件允许,建议使用 RUM 提供商或自行实现 RUM 解决方案,以补充 CrUX 数据。
在实验室中诊断缓慢交互
如果已有现场数据表明某些交互较慢,就可以开始在实验室环境中进行测试。如果没有现场数据,也有一些在实验室中识别缓慢交互的策略,例如:沿着典型的用户操作流程进行测试并在过程中检查交互,或者在页面加载期间操作页面(此时主线程通常最为繁忙)。这有助于在用户体验的关键环节发现延迟问题。
详细信息请参阅:在实验室中诊断缓慢交互。
优化交互过程
在识别出缓慢交互并能在实验室中手动复现后,下一步就是进行优化。
一个完整的交互过程可以分为三个部分:
- 输入延迟:从用户开始与页面交互时起,到交互事件回调开始执行时止。
- 处理时间:事件回调执行完成所需的时间。
- 呈现延迟:浏览器将包含交互视觉结果的下一帧绘制到屏幕所需的时间。

注意: 虽然可以在每个单独输出的事件条目上测量这些子部分,但建议如图所示,在同一帧内输出的所有事件条目(如之前的 pointerup、mouseup、click 条目)上进行测量。这样可以准确判断延迟发生在哪个阶段:是在交互事件处理程序开始处理之前、处理过程中,还是在其完成之后。这也是 web-vitals JavaScript 库 计算子部分的方式。这三个子部分的总和就是交互的总延迟。交互的每个部分都占用总延迟的一定时间,因此了解如何优化每个部分以使其尽可能快地执行至关重要。
关键点: 在优化交互时,理解每个浏览上下文都有自己的主线程非常重要。也就是说,顶级页面有一个主线程,页面上的每个 <iframe> 元素也都有自己的主线程。INP 是在页面级别报告的,包括页面上的缓慢交互以及页面内的 iframe 中的交互。需要确认交互发生在哪个框架中,以确定应该关注哪个主线程。不过,即使存在多个主线程,在资源受限的设备上,看似独立的线程之间也可能相互影响。
识别并减少输入延迟
当用户与页面交互时,该过程的第一阶段就是输入延迟。页面上的其他活动可能导致输入延迟变长,原因可能包括:主线程正在执行其他任务(可能由于脚本加载、解析、编译等)、fetch 请求、定时器函数,或者连续发生且相互重叠的其他交互。
无论导致交互输入延迟的原因是什么,都应尽量减少输入延迟,以使交互的事件回调能够尽快执行。
更多信息请参阅:优化输入延迟。
启动时的脚本评估与长任务
页面生命周期中交互性的一个关键方面是启动阶段。页面加载时会先进行渲染,但页面渲染完成并不一定意味着加载完成。根据页面完全运行所需资源的数量,用户在加载期间可能尝试与页面交互。
脚本评估是导致页面加载期间交互输入延迟变长的原因之一。JavaScript 文件从网络获取后,浏览器在执行前还需要进行处理。这个过程包括解析脚本以检查语法有效性、将其编译为字节码,最后才执行。
根据脚本大小,此处理过程可能导致主线程上出现长任务,从而延长浏览器响应其他用户操作的时间。为了在页面加载期间保持对用户输入的响应性,了解如何减少页面加载期间长任务的可能性,从而保持页面快速响应,这一点非常重要。
更多信息请参阅:脚本评估与长任务。
优化事件回调
输入延迟只是 INP 测量的第一部分。还需要确保由用户操作触发的事件回调能够尽快完成。
频繁让出主线程
优化事件回调最普遍的建议是尽量不在回调内执行过多工作。然而,当交互逻辑复杂时,可能只能略微减少用户的工作量。
如果网站遇到此问题,可以尝试将事件回调的处理拆分为多个独立的任务。这可以防止其成为阻塞主线程的长任务,并允许主线程上等待的其他交互更早执行。
setTimeout 是一种拆分任务的方法,因为传递给它的回调会在新的任务中执行。可以单独使用 setTimeout,也可以将其使用抽象到另一个函数中以获得更好的人体工程学。
// 示例:使用 setTimeout 拆分长任务
setTimeout(() => {
// 这里是被拆分的任务代码
performDeferredWork();
}, 0);
详细信息请参阅:优化长任务。
不加选择地让出主线程比完全不让出要好,但还有更精细的方法:仅在事件回调中立即执行更新用户界面所必需的逻辑,然后将非关键工作推迟到后续任务中,从而使渲染逻辑能够更早执行。
尽早执行渲染工作
更高级的让出技术涉及结构化事件回调代码,将其限制为仅在下一帧视觉更新中需要应用的逻辑。其他所有工作都可以推迟到后续任务中。这不仅使回调更轻量、更敏捷,而且由于事件回调代码不会阻塞视觉更新,因此也能减少交互的渲染时间。
例如,考虑一个富文本编辑器,它不仅要格式化输入的文本,还要根据输入内容更新 UI 的其他方面(例如显示字数、高亮拼写错误等重要的视觉反馈)。此外,应用可能还需要保存用户输入的内容,以防止用户在离开后返回时丢失工作。
在这个例子中,根据用户输入的字符,需要完成以下四项工作。但只有第一项必须在下一帧呈现之前完成:
- 使用用户输入的内容更新文本框,并应用所需的格式。
- 更新显示当前字数的 UI 部分。
- 执行检查拼写错误的逻辑。
- (在本地或远程数据库中)保存最新更改。
代码可以这样组织:
textBox.addEventListener('input', (inputEvent) => {
// 立即更新 UI,使用户所做的更改在下一帧呈现时立即可见。
updateTextBox(inputEvent);
// 使用 `setTimeout` 在 `requestAnimationFrame()` 回调中将所有其他工作至少推迟到下一帧。
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 大小,但这些技术都有其局限性。
使用 content-visibility 延迟渲染屏幕外元素
限制页面加载时和响应用户交互时的渲染工作的一种方法是使用 CSS 的 content-visibility 属性。这相当于在元素接近视口时才进行渲染。有效使用 `content-visibility 需要一定的练习,但它可能带来的渲染时间缩短值得考虑,这有助于改善页面的 INP。
更多信息请参阅:content-visibility:提升渲染性能的新 CSS 属性。
注意使用 JavaScript 渲染 HTML 的性能成本
有 HTML 的地方就有 HTML 解析。浏览器将 HTML 解析为 DOM 后,还需要应用样式、计算布局并将该布局渲染出来。这是不可避免的成本,但 HTML 的渲染方式很重要。
当 HTML 从服务器发送时,它以流的形式到达浏览器。流式传输意味着来自服务器的 HTML 响应是以分块方式到达的。浏览器通过增量解析每个到达的块,并逐步渲染,从而优化了流的处理方式。这是一种“免费”的性能优化,因为浏览器在页面加载期间会自动、隐式地定期让出主线程。
任何网站首次访问时都必然涉及一定量的 HTML,但一种常见的方法是:从最少的初始 HTML 开始,然后使用 JavaScript 填充内容区域的数据。该内容区域的后续更新也通常是用户交互的结果。这通常被称为单页面应用程序(SPA)模型。这种模式的一个缺点是,在客户端使用 JavaScript 渲染 HTML 不仅会产生创建 HTML 的 JavaScript 处理成本,而且在浏览器完成对该 HTML 的解析和渲染之前,不会让出主线程。
不过,即使是非 SPA 网站,也可能因交互结果而通过 JavaScript 渲染一定量的 HTML。通常这没有问题,但重要的是要理解这种方法对性能的影响,特别是在需要使用 JavaScript 渲染大量 HTML 时,它如何影响网站对用户输入的响应性。
详细信息请参阅:HTML 的客户端渲染与交互性。
总结
改善网站的 INP 需要一个迭代的过程。修复了现场发现的缓慢交互后,尤其是在提供大量交互功能的网站上,很可能还会发现其他缓慢的交互,这些也需要进行优化。
优化 INP 的关键在于坚持。花时间持续优化,才能打造出令用户满意的、响应迅速的页面。在为用户开发新功能时,也可能需要遵循同样的交互优化流程。虽然需要投入时间和精力,但其带来的用户体验提升是值得的。

正在加载评论...