《经济时报》挑战 INP 问题

《Ecomonic Times》将 TBT 缩短了 30 次并迁移到 Next.js,这帮助 The Ecomonic Times 将 INP 降低了将近 4 倍,从而使跳出率降低了 50%,网页浏览量提升了 43%。

Daya Ram Yadav
Daya Ram Yadav
Saurabh Rajpal
Saurabh Rajpal

Interaction to Next Paint (INP) 指标用于评估网站对用户输入的响应情况。良好的响应速度意味着网页可以快速响应用户互动。网页的 INP 越低,就越能更好地响应用户互动。

良好的 INP 值不超过 200 毫秒,不佳的值大于 500 毫秒,介于两者之间的所有值都需要改进。

迷幻的开始

当 Google 最初将 INP 作为一项有可能演变成核心网页指标的实验性指标时,《经济时报》团队就参与了这项挑战,在它正式推出之前就解决了这个问题,因为提供世界级的用户体验对我们的核心业务价值至关重要。

INP 一直是迄今为止最难解决的指标之一。一开始,我们不清楚如何有效衡量 INP。让问题变得更加困难的是缺乏社区支持,包括大多数真实用户监控 (RUM) 提供商尚不支持此功能。不过,我们拥有 Chrome 用户体验报告 (CrUX) 等 Google RUM 工具、web-vitals JavaScript 库以及其他支持这些工具的工具,这让我们能够了解我们在评估未来发展之路时所处的位置。开始时,我们的 INP 接近源级的 1,000 毫秒。

实际运行中修复 INP 时,出现了一个要确定的目标实验指标,即总阻塞时间 (TBT)。TBT 已有完备的说明文档,得到了社区的支持。尽管已经达到 Core Web Vitals 的阈值,但在 TBT 方面,表现却不那么理想,因为开始时超过了 3 秒。

什么是 TBT,我们采取了哪些措施对其进行改进?

TBT 是一项实验室指标,用于衡量网页在网页加载过程中对用户输入的响应情况。任何执行时间超过 50 毫秒的任务都被视为长时间运行的任务,50 毫秒阈值之后的时间称为阻塞时间

TBT 的计算方法是:取网页加载期间所有耗时较长的任务的阻塞时间总和。例如,如果在加载期间有两个耗时较长的任务,阻塞时间将按以下方式确定:

  • 任务 A 用时 80 毫秒(30 毫秒比 50 毫秒多)。
  • 任务 B 用时 100 毫秒(50 毫秒比 50 毫秒多)。

网页的 TBT 为:80 毫秒 (30 + 50)。TBT 越低越好,TTBT 也与 INP 具有较高的相关性

下方列出了在采取措施改进 TBT 之前和之后的待定实验对比情况:

<ph type="x-smartling-placeholder">
</ph> 启动期间长时间运行的任务的合成图片(如 Chrome 开发者工具的性能面板中所示),以及页面指标的报告。主线程在网页加载期间会阻塞 3,260 毫秒。 <ph type="x-smartling-placeholder">
</ph> 优化 TBT 之前启动期间的主线程。TBT 为 3,260 毫秒。
<ph type="x-smartling-placeholder">
</ph> 启动期间长时间运行的任务的合成图片(如 Chrome 开发者工具的性能面板中所示),以及页面指标的报告。主线程在网页加载期间会阻塞 120 毫秒。
优化 TBT 后启动期间的主线程。TBT 为 120 毫秒。

最大限度地减少主线程工作

浏览器的主线程负责处理从解析 HTML、构建 DOM、解析 CSS 和应用样式到评估和执行 JavaScript 的所有工作。主线程还处理用户互动,即点击、点按和按键。如果主线程正忙于执行其他工作,它可能无法有效地响应用户输入,并且可能导致用户体验卡顿。

对我们来说,这是最困难的任务,因为我们拥有自己的算法,可以根据订阅状态检测用于投放广告的用户身份,以及用于 A/B 测试、分析等用途的第三方脚本。

最初,我们只采取了小措施,例如降低加载不太重要的业务资源的优先级。其次,我们将 requestIdleCallback 用于非关键工作,这有助于减少 TBT。

if ('requestIdleCallback' in window) {
  this.requestIdleCallbackId = requestIdleCallback(fetchMarketsData.bind(this), {timeout: 3000});
} else {
  fetchMarketsData(); // Fallback in case requestIdleCallback is not supported
}

建议在使用 requestIdleCallback 时指定超时,因为这样可以确保在给定时间已过且回调尚未调用的情况下,它会在超时后立即执行回调。

最大限度地缩短脚本评估时间

我们还使用可加载的组件延迟加载第三方库。我们还使用 Chrome 开发者工具中的覆盖率工具来分析网页,从而移除了未使用的 JavaScript 和 CSS。它帮助我们确定了需要进行摇树优化的区域,以便在页面加载期间减少代码,从而减小应用的初始软件包大小。

Chrome 开发者工具中覆盖率工具的屏幕截图。在这里,该工具会在网页加载期间显示 JavaScript 和 CSS 文件未使用的部分。

缩减 DOM 大小

根据 Lighthouse 的要求,大型 DOM 会增加内存使用量,导致样式重新计算用时更长,并产生高昂的布局重排成本。

Lighthouse 中 DOM 大小审核的屏幕截图。报告的 DOM 元素数量为 2,706 个。

我们通过以下两种方式减少了 DOM 节点的数量:

  • 首先,我们应用户的请求(在用户点击时)呈现菜单项。它将 DOM 大小减少了约 1,200 个节点。
  • 其次,我们延迟加载不太重要的 widget。

通过所有这些努力,我们大幅减少了 TBT,并将 INP 降低了近 50%:

CrUX 中的 INP 审核的屏幕截图。网页的 INP 为 539 毫秒,超出了“糟糕”的阈值。

至此,我们几乎没有了可进一步降低 TBT(和 INP)的轻松制胜法宝,但我们知道还有很大的改进空间。就在那时,我们决定将我们定制的界面样板代码连同 Next.js 一起升级到最新版本的 React,以便更好地利用钩子,避免不必要的组件重新渲染。

由于与网站的其他部分相比,更新频率和流量相对较少,因此我们开始将主题页面迁移到 Next.js。我们还使用 PartyTown 将额外的繁重主线程工作分流给 Web Worker,并采用 requestIdleCallBack 等技术来延迟非关键任务。

改进 INP 对《经济时报》有何帮助?

源国家/地区的当前 TBT 和 INP

在发布这篇博文时,我们源的 TBT 已从我们开始优化时的 3,260 毫秒减少到 120 毫秒。同样,我们源的 INP 也是在我们完成优化工作后 257 毫秒,低于原来的 1,000 毫秒。

CrUX 中的 INP 审核的屏幕截图。网页的 INP 为 257 毫秒,在“需要改进”范围内阈值。

INP CrUX 趋势

主题网页获得的流量在总流量中所占的比例要小得多。因此,这是一个进行实验的理想场所。CrUX 取得的成果以及业务成果都非常鼓舞人心,促使我们在整个网站上扩大工作范围,以进一步获益。

CrUX 在 2022 年 7 月到 2022 年 10 月期间的四个月内 INP 分布情况的屏幕截图。“poor”中的值和“需要改进”阈值有所降低,而“良好”值范围内的值阈值提高了。

Akamai mPulse TBT 分析

我们使用 Akamai mPulse 作为我们的 RUM 解决方案,可在现场测量 TBT。我们观察到 TBT 持续下降,这与减少 INP 所取得的成效明确对应。如下面的屏幕截图所示,TBT 值最终从大约 5 秒缩短到大约 200 毫秒。

Akamai mPulse 中一张图表的屏幕截图,显示 TBT 在大约一个月内下降。

业务成效

总体而言,我们努力将 TBT 缩短了 30 倍,并迁移到 Next.js,帮助我们将 INP 降低了将近 4 倍,这最终使主题页面的跳出率降低了 50%,网页浏览量提高了 43%

Google Analytics 在对比网页浏览量与跳出率的屏幕截图。在《经济时报》网站上对 INP 进行优化后,跳出率降低了 50%,网页浏览量提高了 43%。

总结

总而言之,INP 为确定《经济时报》网站部分版块的运行时性能问题提供了极大的帮助。事实证明,它是对业务成果产生积极影响的最有效指标之一。通过此次努力,我们取得了非常鼓舞人心的成果,我们有动力将优化措施扩展到网站的其他区域,以获得更多收益。