《经济时报》挑战 INP 问题

将 TBT 缩短了 30 倍并迁移到 Next.js 后,The Ecomonic Times 将 INP 缩短了近四倍,跳出率降低了 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 是最难解决的指标之一。起初,我们不确定如何有效衡量 INP。更令人头疼的是,缺少社区支持,包括大多数实时用户监控 (RUM) 提供商尚不支持它。不过,我们有 Chrome 用户体验报告 (CrUX)web-vitals JavaScript 库 等 Google RUM 工具以及其他支持工具,这让我们在评估未来的发展方向时,能够了解自己的现状。刚开始时,我们的 INP 在源级别接近 1,000 毫秒。

现场修复 INP 时,我们发现可定位的一个实验室指标是 Total Blocking Time (TBT)。TBT 已经有详细的文档,并得到了社区的支持。不过,尽管已经达到了核心 Web 指标的阈值,但在 TBT 方面,我们表现不佳,因为在开始时,该指标超过了 3 秒。

什么是 TBT?我们采取了哪些措施来改进它?

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

TBT 的计算方法是将网页加载期间所有长任务的阻塞时间相加。例如,如果加载期间有两个长任务,则阻塞时间的确定方式如下:

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

网页的 TBT 为 80 毫秒(30 + 50)。TBT 越低越好,并且 TBT 与 INP 之间也存在很强的相关性

下面的实验简要比较了采取措施改进 TBT 前后的效果:

启动期间长任务的复合图片(如 Chrome DevTools 的“Performance”面板中所示),以及网页指标报告。主线程在网页加载期间阻塞了 3,260 毫秒。
优化 TBT 之前,启动期间的主线程。TBT 为 3,260 毫秒。
启动期间长任务的复合图片(如 Chrome DevTools 的“Performance”面板中所示),以及网页指标报告。主线程在网页加载期间阻塞了 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 DevTools 中覆盖率工具的屏幕截图。在这里,该工具会显示网页加载期间 JavaScript 和 CSS 文件的未使用部分。

缩减 DOM 大小

根据 Lighthouse 的说法,DOM 大小过大会增加内存用量、导致样式重新计算用时延长,并产生高昂的布局自动重排费用。

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

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

  • 首先,我们会在用户请求时(点击时)呈现菜单项。这会将 DOM 大小缩减约 1,200 个节点。
  • 其次,我们延迟加载了重要性较低的 widget。

通过这些努力,我们大幅缩短了 TBT,相应地 INP 也减少了近 50%:

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

至此,我们几乎已经用尽了可轻松降低 TBT(以及通过代理的 INP)的方法,但我们知道仍有很大的改进空间。因此,我们决定将自定义界面样板升级到最新版本的 React 和 Next.js,以便更好地利用钩子来避免不必要地重新渲染组件。

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

提高 INP 对《经济时报》有何帮助?

来源的当前 TBT 和 INP

在发布这篇文章时,我们源站的 TBT 为 120 毫秒,比我们开始优化时的 3,260 毫秒缩短了许多。同样,在我们进行优化后,源的 INP 从超过 1,000 毫秒降到了 257 毫秒。

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

INP CrUX 趋势

主题页面获得的流量在总流量中所占的比例要小得多。因此,这是一个理想的实验场所。CrUX 带来的成效和业务成果令人鼓舞,这促使我们在整个网站上扩大了改进力度,以期进一步提升成效。

一张屏幕截图,显示了 2022 年 7 月至 2022 年 10 月这四个月内 INP 分布情况(在 CrUX 中可视化)。“较差”和“有待改进”阈值范围内的值有所下降,而“良好”阈值范围内的值有所上升。

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 帮助我们全面确定了《经济时报》网站的某些部分存在的运行时性能问题。事实证明,转化次数是影响业务成效的最有效指标之一。由于我们在执行这项工作后取得了非常令人鼓舞的结果,因此我们有动力将优化工作扩展到网站的其他方面,从而获得更多好处。