Interaction to Next Paint - 输入延迟
了解如何发现和改善由输入延迟引起的 INP 问题
由输入延迟引起的 Interaction to Next Paint (INP) 问题
在我们之前的文章中,我们讨论了 Interaction to Next Paint 以及如何识别 Interaction to Next Paint 问题。如果您想了解基础知识,这是一个很好的起点!
在本文中,我将重点介绍'输入延迟'。它如何影响 Interaction to Next Paint 问题,以及如何最小化输入延迟以改善 Interaction to Next Paint。
INP 提示:大多数情况下,输入延迟会在网页加载的早期阶段发生!
Table of Contents!
什么是输入延迟?

输入延迟是指用户与网页交互(例如点击按钮或按下按键)后,浏览器开始处理事件回调所需的时间。虽然总是存在一些输入延迟(即使是浏览器也需要时间来调度回调),但当浏览器忙于执行其他已调度的任务而无法立即调度交互请求的回调时,输入延迟就会发生。
输入延迟与 INP
Interaction to Next Paint (INP) 可以分为三个子部分:'输入延迟'、'处理时间'和'呈现延迟'

您可能会注意到输入延迟与较早的 Core Web Vital 指标 'First Input Delay' 之间存在命名相似性。对于不了解的人来说:Interaction to Next Paint 是已退役的 'First Input Delay' 的继任者。First Input Delay 测量的是第一次交互与事件回调之间的时间。尽管 First Input Delay 已经退役,'输入延迟'在改善网页响应能力方面仍然发挥着重要作用,因为输入延迟是每次 Interaction to Next Paint 的基础。
输入延迟的重要性
由于许多开发人员在改善 INP 时会想到优化回调函数(优化处理时间),'输入延迟'往往被忽视。诚然,输入延迟通常不是 INP 中最大的部分,但尽管如此,如果我们优化输入延迟,我们通常会同时优化所有 INP 交互!

在 CoreDash,我们每小时收集数百万个 Core Web Vitals 数据点。根据这些数据,输入延迟仅占 Interaction to Next Paint 的 18%。虽然这远不及呈现延迟或处理时间那么多,但仍然是一个重要的组成部分。
输入延迟的原因:
当主线程忙于执行其他任务时,就会发生输入延迟。这些任务可能来自:

- 早期任务。在早期排队的普通脚本、延迟脚本和异步脚本会创建早期任务
- 计划任务。某些任务不会在页面加载开始时运行,而是可能被安排在页面加载完成后执行。这些任务也可能干扰 INP 并导致输入延迟。例如在
window.onload事件之后运行的脚本 或被所谓的优化插件延迟的脚本。 - 重复任务。通过
setInterval()执行的周期性任务,如果执行时间相对较长并与 INP 同时发生 - 重叠回调:重叠回调是输入延迟的常见原因。多个紧密排列的回调会创建队列,延迟下一个交互的处理。
最小化输入延迟
- 将长的早期任务分解为多个较小的任务。在长任务期间,浏览器无法响应用户输入,而在每个短任务之后,浏览器可以响应用户输入。因此,使用
scheduler.yield()(实验性)或通过将每个函数包装在超时为 0 的setTimeout(callback,0)中来分解长任务 - 管理交互元素。考虑在控制交互元素(如搜索栏)的 JavaScript 代码完全加载之前不展示这些元素。这将防止对尚未准备好接收点击的元素进行早期点击。要优化此模式的 UX,您可以优先加载必要的 JavaScript 或暂时隐藏/禁用元素,直到其功能正常。
- 空闲时间脚本执行:使用
requestIdleCallback()将非关键脚本安排在浏览器空闲期间运行。requestIdleCallback 在浏览器空闲且不需要处理用户输入时运行。 - 使用 Web Workers 在浏览器主线程之外运行 JavaScript。Web Workers 允许脚本在主线程之外运行。这将防止主线程阻塞并导致 INP 输入延迟问题。
- 在重复任务中检查待处理输入。在执行一组或计划任务之前,先检查是否有待处理的输入。如果有任何待处理的输入,请先让出主线程。
- 移除不需要的代码。定期审查您的脚本,移除任何不必要的代码甚至脚本,因为每一行代码都可能导致影响 Interaction to Next Paint 的输入延迟。
async function yieldToMain() {
if ('scheduler' in window && 'yield' in window.scheduler) {
return await window.scheduler.yield();
}
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
实际应用
让我们来回答最重要的问题:'这一切对我的网站意味着什么'。让我们分别针对 WordPress 和 REACT 来分析。
WordPress
WordPress 由于其特性,通常配备一个主题和大量插件。插件和主题通常都依赖 JavaScript 来实现功能。由于这些插件和主题由第三方开发者维护,我们无法控制其内容。这意味着我们无法更改文件和优化'糟糕的代码'。即使脚本目前表现良好,也不能保证将来也是如此。
因此,为了最小化输入延迟并优化 Interaction to Next Paint (INP),请执行以下操作:
- 尽可能避免使用插件。虽然插件是添加功能的简便方法,但它们通常会向页面添加脚本。这些脚本会导致影响 INP 的输入延迟。对于每个插件,问问自己:我能用自定义代码实现相同的功能吗?
- 选择轻量级主题。许多 WordPress 主题'提供一切'。虽然这看起来是个好主意,但这意味着它们可能充满了未使用但占用宝贵 CPU 时间的功能。
- 避免使用页面构建器。页面构建器(如 Elementor 或 WPBakery)为您提供了用户友好的可视化界面来构建布局。不幸的是,它们通常依赖脚本向访问者展示这些布局。
- 仅在需要时加载脚本。WordPress 倾向于在所有页面上加载所有脚本。要解决此问题,只需创建子主题并按页面类型取消注册不需要的脚本。例如:
function my_deregister_scripts() {
if ( ! is_page( 'contact' ) ) {
// Example: Deregister contact form script on non-contact pages
wp_dequeue_script( 'contact-form-script' );
}
}
add_action( 'wp_enqueue_scripts', 'my_deregister_scripts' );
REACT / NextJS
React 或 NextJS 网站主要由 JavaScript 驱动。执行这些脚本需要时间,并会导致 Interaction to Next Paint (INP) 的输入延迟
- 使用服务器组件。服务器组件在服务器端渲染而不是在客户端渲染,这将减少 JavaScript 的数量
- 使用正确的策略加载第三方脚本。在 hydration 之后甚至在浏览器空闲时间加载第三方脚本
- 实现空闲直到紧急模式:此模式将用户交互优先于后台任务,并在浏览器使用 requestIdleCallback 在空闲期间执行非关键任务时创建临时状态。
- 懒加载组件。使用
React.lazy()或 NextJSdynamic()懒加载不立即需要的组件 - 对交互组件使用 Suspense。考虑仅在客户端渲染需要 hydration 才能变为可交互的交互组件。
Your dev team is busy.
Delegate the performance architecture to a specialist. I handle the optimization track while your team ships the product.
- Parallel Workflows
- Specialized Expertise
- Faster Delivery