Economic Times 探索解决 INP

将 TBT 降低 30 倍并迁移到 Next.js 帮助《经济时报》将 INP 降低了近四倍,从而使跳出率降低了 50%,页面浏览量提高了 43%。

下次绘制互动 (INP) 是一个评估网站对用户输入响应速度的指标。良好的响应速度意味着页面能够快速响应用户互动。页面 INP 值越低,其响应用户互动能力就越好。

Good INP values are 200 milliseconds or less, poor values are greater than 500 milliseconds, and anything in between needs improvement.

模糊的开始

当 Google 最初引入 INP 作为一项实验性指标,并有可能发展成为 Core Web Vitals 指标之一时,《经济时报》团队接受了挑战,要在它成为核心指标之前解决这个问题,因为提供世界一流的用户体验对我们的核心业务价值观至关重要。

INP 是迄今为止最难解决的指标之一。起初,如何有效衡量 INP 并不明确。更困难的是缺乏社区支持,包括大多数真实用户监控 (RUM) 提供商尚未支持它。但是,我们有 Google RUM 工具,例如 Chrome 用户体验报告 (CrUX)web-vitals JavaScript 库以及其他支持它的工具,这让我们在评估前进方向时了解了自己的处境。当我们开始时,我们的 INP 在源站级别接近 1,000 毫秒。

现场修复 INP 时出现的一个情况是,可以作为目标实验室指标之一是 Total Blocking Time (TBT)。TBT 已经有完善的文档记录并获得社区支持。尽管我们已经达到了 Core Web Vitals 的阈值,但我们在 TBT 方面做得不太好,因为当我们开始时它超过 3 秒。

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

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

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

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

页面的 TBT 将为:80 毫秒 (30 + 50)。TBT 值越低越好,并且 TBT 也与 INP 密切相关

以下是我们在采取措施改进 TBT 前后进行的快速实验室比较

A composite image of long tasks during startup as shown in the performance panel of Chrome DevTools, and a report of page metrics. The main thread is blocked during page load for 3,260 milliseconds.
优化 TBT 前启动期间的主线程。TBT 为 3,260 毫秒。
A composite image of long tasks during startup as shown in the performance panel of Chrome DevTools, and a report of page metrics. The main thread is blocked during page load for 120 milliseconds.
优化 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 时,建议指定超时时间,因为它确保如果在给定时间已过且回调尚未被调用,它将在超时后立即执行回调。

最大限度地减少脚本评估时间

我们还使用 Loadable components 延迟加载了第三方库。我们还通过使用 Chrome DevTools 中的覆盖率工具分析页面,删除了未使用的 JavaScript 和 CSS。这帮助我们确定了在哪些区域需要 tree shaking 以在页面加载期间减少代码传输,从而减小应用程序的初始捆绑包大小。

A screenshot of the coverage tool in Chrome DevTools. Here, the tool displays unused portions of JavaScript and CSS files during page load.

减小 DOM 大小

根据 Lighthouse 的说法,大型 DOM 会增加内存使用量,导致更长的样式重新计算,并产生代价高昂的 布局重排

A screenshot of the DOM size audit in Lighthouse. The number of DOM elements reported is 2,706 elements.

我们通过两种方式减少了 DOM 节点数

  • 首先,我们在用户请求时(点击时)渲染菜单项。这使 DOM 大小减少了约 1,200 个节点。
  • 其次,我们延迟加载了不太重要的 Widget。

由于所有这些努力,我们显著降低了 TBT,并且我们的 INP 也相应地降低了近 50%。

A screenshot of the INP audit in CrUX. The INP for the page is 539 milliseconds, which exceeds the 'poor' threshold.

在这一点上,我们几乎用尽了进一步降低 TBT(以及间接降低 INP)的简单方法,但我们知道我们还有很大的改进空间。这时我们决定将我们自定义构建的 UI 样板升级到最新版本的 React 以及 Next.js,以便更好地利用 Hook 来避免不必要的组件重新渲染。

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

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

源站上当前的 TBT 和 INP

在发布此文章时,我们源站的 TBT 为 120 毫秒,比我们开始优化工作时的 3,260 毫秒有所下降。同样,经过我们的优化工作,我们源站的 INP 为 257 毫秒,比之前的 1,000 多毫秒有所下降。

A screenshot of the INP audit in CrUX. The INP for the page is 257 milliseconds, which is within the 'needs improvement' thresholds.

INP CrUX 趋势

主题页面收到的流量占总流量的比例要小得多。因此,它是进行实验的理想场所。CrUX 结果以及业务成果非常令人鼓舞,促使我们将我们的努力扩展到整个网站,以获得更多好处。

A screenshot of INP distributions as visualized in CrUX over a period of four months, starting in July 2022 and ending in October 2022. Values within the 'poor' and 'needs improvement' thresholds declined somewhat, while the values within the 'good' threshold increased.

Akamai mPulse TBT 分析

我们使用 Akamai mPulse 作为我们的 RUM 解决方案,它用于衡量现场的 TBT。我们观察到 TBT 持续下降,这清楚地反映了我们为降低 INP 所做的努力的结果。如下面的屏幕截图所示,现场的 TBT 值最终从大约 5 秒降至约 200 毫秒。

A screenshot of a chart in Akamai mPulse, showing a decline in TBT over the course of roughly a month.

业务成果

总的来说,我们将 TBT 降低 30 倍的努力,以及迁移到 Next.js,帮助我们将 INP 降低了近 4 倍,这最终导致主题页面的跳出率降低了 50%,页面浏览量提高了 43%

A screenshot of Google Analytics comparing pageviews versus bounce rate. Because of the optimizations made to INP on The Economic Times website, a 50% decrease in bounce rate and a 43% increase in pageviews was realized.

结论

总而言之,INP 在很大程度上帮助确定了《经济时报》网站部分区域的运行时性能问题。它已被证明是积极影响业务成果的最有效指标之一。由于我们通过这项努力观察到了非常令人鼓舞的数字,我们有动力将我们的优化工作扩展到我们网站的其他区域,并获得更多好处。