为什么 Lighthouse 10.0 取消了 TTI 作为观测指标?

发布于:2024-05-06 ⋅ 阅读:(28) ⋅ 点赞:(0)

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

引言

是一款网站审核工具,可为开发者提供优化建议和诊断信息,帮助他们改善网站的用户体验。

自 V10.0 发布之后,Lighthouse 移除了  指标,将 TTI 为 10% 的得分权重转变为。

这篇文章中就来和大家聊聊 LightHouse 为什么从页面关键性能指标中放弃可交互时间 (TTI) 。

TTI

概念

TTI 全称 Time to Interactive (可交互时间),TTI 指标用于衡量从网页开始加载到其主要子资源加载完成所用的时间,并且能够快速可靠地响应用户输入。

简单来说 TTI 指标代表用户从看到我们的 Web 页面到可操作时间的响应耗时。

一个非常常见的场景,通常在页面加载过程中我们的 Web 网页已经展示给用户足够的 UI 元素时,但存在页面交互逻辑的 JavaScript 脚本并为加载(执行完毕),此时页面虽然可以正常向用户展示内容但无法响应用户的交互式命令。

当用户点击已展示的 UI 元素时页面并没有任何交互式反应(可能此时 JavaScript 文件还在下载阶段、又或者 JavaScript 在执行过程中主线程被阻塞),可交互时间 TTI 的初衷正是作为评估这部分从看到到可操作的指标而生。

计算方式

根据网页表现来计算 TTI 是一件较为复杂的事情,计算可交互时间不仅仅要满足网页的所有主要资源加载完成的条件同时还要确保页面可以快速的响应用户的输入。

重点就在于,我们应该如何确定页面可以快速响应用户的输入较为模糊的含义。

熟悉浏览器的朋友都清楚浏览器是一个多进程模型,在渲染进程中有一个所谓的主线程(Main Thread),几乎所有我们编写的 JavaScript 都会在该线程中执行。

主线程一次只能处理一个任务。浏览器会将任何耗时超过 50 毫秒的任务均算作 long task (长任务)

如果用户尝试在长时间的任务(long task)或渲染更新期间与页面互动,此时浏览器不得不等待主线程执行完成后才能对用户的命令作为响应,从而导致卡顿延迟的现象发生。

自然,我们可以通过 Long Task 任务的完成时间衡量页面是否可以快速响应用户的输入,从而计算出页面 TTI 的耗时。

TTI 的标准计算方式可以分为以下四个步骤:

  1. 从第一次有内容的绘制  开始计算。

  2. 从前往后查找一个静默 5s 的安静窗口,安静窗口指得是:没有 ,且不超过两个进行中的网络 GET 请求。

  3. 从后往前查找静默窗口之前的最后一个长任务的结束时间,如果找不到长任务,则停止在 FCP 处停止。

  4. TTI 是安静窗口之前的最后一个长任务的结束时间(如果未找到长任务,则与 FCP 值相同)。

image.png

借助 web.dev 上的一张 TTI 解释图,我们可以清晰的看到在上图中,页面到 FCP 阶段后(1 位置)从前往后开始往后查找。

首先向后查找到静默 5s 的安静窗口(图中灰色区域),因为从 FCP 开始往后搜索满足不超过两个进行中的网络 Get 请求以及同时不存在 Long Task 执行的 5s 时间段中,图中只有灰色区域是满足的,自然我们认为灰色区域为 5s 的安静窗口

之后,根据查找规则中第三点的描述。寻找到静默窗口后,从静默窗口的开始时间从后往前查找,寻找静默窗口开始时间之前的最后一个 long task 长任务的结束时间。

最后 TTI 的时间就是图中 4 红线所在的位置,标准计算方式下 Google 会认为该时间为 Web 页面的可交互时间。

TTI 的误差

误差

TTI 的设计初衷源自于页面在主线程空闲之前并不会真正“加载”的想法,所以通过 Lighthouse 的 TTI 的评分开发者们可以直观的观察到页面具备“响应用户的输入”的标准耗时。

刚刚在上边的章节中我们也聊到过 TTI 的计算规则,TTI 的这一套计算规则对于异常边界下和 Long Task 过于敏感,不同的条件下会导致 TTI 的指标的可变性非常高。

同时,由于 TTI 的计算方式就决定了具有相同 TTI 的站点可能会具有截然不同的用户负载体验。

上边我们说过 TTI 计算规则中的 2、3 两点:

  1. 从前往后查找一个静默 5s 的安静窗口,安静窗口指得是:没有 ,且不超过两个进行中的网络 GET 请求。

  2. 从后往前查找静默窗口之前的最后一个长任务,如果找不到长任务,则停止在 FCP 处停止。

不难想象,如果两个不同的网站。5s 静默窗口的时间之前,一个具有 10s Long Task 和有两个 51ms 任务的页面可能会具有相同的 TTI 表现:

image.png

比如上图中两个完全不同的网页,按照 TTI 的计算规则拥有 10s longtask 的网页 A 和 拥有两个 51ms longtask 任务的网页 B 具有相同的 TTI 分数表现。

显然,Page A 和 page B 对于真实用户体验来说一定是截然不同的两个 Web Page。但是在这一套计算标准下可能会给出同样的分数。

不置可否的是,在 LightHouse V8 时引入的 TTI 的确是一项革命性的指标,通过页面 LongTask 任务来评测主线程是否空闲从而反映页面在首屏加载的可交互耗时。

不过,TTI 这种计算方式的确也存在一定的误差和可变性,随着 Lighthouse 中提出了更多可以更加精准的衡量用户交互耗时(比如 FID 和 TBT)的体验后,自然 TTI 也就退出了历史舞台。

更加准确的交互指标

TBT

TBT 全称为 Total Blocking Time (总阻塞时间)。它测量第一次有内容绘制(FCP)后主线程被阻止的时间以阻止,从而判断页面首次加载时对用户输入的响应的总时间。

默认情况下,在页面 TTI 来临之后 TBT 的计算时间就会终止(TBT 会计算在 FCP 至 TTI 之间的所有 long task 阻塞耗时)。

简单来说在 FCP 和 TTI 之间,当页面存在存在长任务(Long Task)时主线程就会被视为”Block“,所谓 Total Blocking Time 正是衡量这段时间内的页面阻塞总时长。

比如下图中:

image.png

之前我们提到过所谓 long task 的概念,即超过 50ms 的长任务会被算作长任务,所以按照上图中的时间轴来计算 TBT 的话会拆分为:

image.png

上图中的 5 个任务,其实中三个任务的执行时间占用主线程超过 50ms ,所以总的 TBT 时间会是 200 + 40 + 105 = 345 ms。

相较于 TBT 的时常来衡量页面的可交互时间会比 TTI 更加准确,上述 TTI 面临一个 10s 的长任务下和两个 51ms 的长任务可能会得到相同的 TTI 评分。

但是使用 TBT 来衡量在首次页面加载时的 long task (阻塞用户交互行为的时间)则是完全不同的,两个 51ms long task 的 TBT 时间仅为 2ms 而 10s long task 的阻塞时间则会是 900 ms。

FID

TBT 旨在全面的衡量页面首次加载时,FCP 与 TTI 之间的时间段中阻塞用户交互的总时长,而当用户真正发生交互行为时由于交互发生时的随机性(或许刚好在 Blocking Time 又或许此时并没有任何任务在执行)。

而首次加载页面时,当用户真正与页面中的元素发生交互时我们可以通过 FID (First Input Delay)来衡量用户的真实输入延迟。

FID 是用来衡量用户首次与网页互动(即,点击链接、点按按钮或使用由 JavaScript 提供支持的自定义控件)到浏览器实际能够开始处理事件处理脚本以响应相应互动的时间。

FID 同样也是发生在 FCP 和 TTI 之间的时间段,这是因为此阶段网页已渲染部分内容,尚不存在可靠地互动。

借助 Web.dev 上的一张图来让我们一起理解 FID:

image.png

在页面第一帧的渲染之后,一直到 TTI 结束主线程中总共出现了 5 个 task,可以看到位于第三个 long task 时用户操作了页面,此时由于主线程被 long task 占用无法释放,自然用户的事件也无法及时做出响应,而这部分需要等待 long task 执行完成后才可响应用户交互行为的时间被称为 Fist Input Delay:

image.png

需要额外留意的是由于 FID 依赖于页面首次加载后的交互行为,所以不同用户交互下会造成不同的 FID 表现。

如果在衡量 FID 期间用户并未进行任何页面操作或者页面元素并不具备任何事件(交互行为,比如 a、input 等具有交互性质的元素)FID 自然并不具备任何值。

2024-9-9 后 FID 已经不再是 Core Web Vitals 指标了,已被 取代。

INP 可以理解为 FID 的优化指标:

  • 范围纬度上:FID 仅测量页面的首次互动的输入延迟而 INP 则会考虑页面所有的交互。

  • 指标类型上:FID 仅为主线程中 long task 的 block 掉的时间,而 INP 包含从输入延迟到运行事件处理程序,再到浏览器绘制下一帧的整体耗时。纬度上 INP 更加接近用户的真实感受。

有兴趣全面了解 的朋友可以参考 web.dev 的解释。

如何测试 Web 性能指标

是 GoogleChrome 提供的小型(~1.5K)的用户性能指标测量 Library。

当我们需要测量、记录页面的 FCP、LCP、CLS、FID 等核心性能指标时,web-vitals 为我们提供了简洁的 API 来满足我们的需求。

<!-- Append the `?module` param to load the module version of `web-vitals` -->
<script type="module">
  import {
    onCLS,
    onFID,
    onLCP,
  } from 'https://unpkg.com/web-vitals@3/dist/web-vitals.attribution.js?module';

  onCLS(console.log);
  onFID(console.log);
  onLCP(console.log);
</script>

web-vitals 的用法非常简介,只需要引入对应的测量 Api 然后调用该方法后 web-vitals 就会帮助我们在页面的各个阶段进行测量从而将结果调用传入的 callback 方法供我们使用。

它的使用方法非常简单,有兴趣了解 web-vitals 的同学可以自行翻阅 进行使用。

结尾

文章从 Google 放弃使用 TTI 作为核心衡量指标延伸到 TTI 的后续替代指标 TBT 以及 FID 的概念和计算方式,为大家讲述为什么 Lighthouse v10.0.0 之后放弃了 TTI 作为页面性能观察指标。

文章到这里就要结束了,希望文章中的内容可以帮助到大家。