性能之Web性能关键点(Web Vitals)

3,690 阅读36分钟

参考:

概述

指标,为了确保大多数用户都达到了推荐的目标,一个很好的衡量阈值是页面加载的第75个百分位数,该值在移动和桌面设备上进行了划分。

要了解有关这些建议背后的研究和方法的更多信息,请参阅:定义核心网络关键指标阈值

指标

首次内容绘制(First Contentful Paint,FCP)

First Contentful Paint(FCP)是一个重要的、以用户为中心的度量标准,用于测量感知的加载速度,因为它标记了页面加载时间轴中用户可以在屏幕上看到任何内容的第一个点—快速FCP有助于让用户确信发生了某些事情。

First Contentful Paint(FCP)度量从页面开始加载到页面内容的任何部分在屏幕上呈现的时间。对于这个度量,“内容”是指文本、图像(包括背景图像)、元素或非白色元素。 在上面的加载时间轴中,FCP发生在第二帧,因为这是第一个文本和图像元素呈现到屏幕的时候。

您会注意到,尽管部分内容已呈现,但并非所有内容都已呈现。这是区分First Contentful Paint(FCP)和 Largest Contentful Paint (LCP)的重要区别,后者的目的是测量页面的主要内容何时完成加载。

为了提供良好的用户体验,网站应该努力在页面开始加载的1秒内出现第一个内容丰富的绘画。为了确保大多数用户都能达到这一目标,一个很好的衡量标准是页面加载的第75个百分位值,这个值在移动设备和桌面设备上进行了划分。

最大内容绘制(Largest Contentful Paint , LCP)

最大内容绘制(LCP)是一个重要的、以用户为中心的度量标准,用于测量感知的加载速度,因为它标记页面加载时间轴中页面的主要内容可能已加载的时间点—快速的LCP有助于向用户保证页面是有用的。

从历史上看,衡量web页面的主要内容的加载速度以及对用户的可见程度一直是web开发人员面临的一个挑战。

像load或DOMContentLoaded这样的旧度量并不好,因为它们不一定与用户在屏幕上看到的内容对应。而更新的、以用户为中心的性能指标(如firstcontentful Paint,FCP)只捕获了加载体验的最初阶段。如果一个页面显示一个启动屏幕或显示一个加载指示器,那么这个时刻与用户并不是很相关。

在过去,我们推荐了一些性能指标,如 First Meaningful Paint (FMP)和Speed Index(SI)(Lighthouse中都有),以帮助捕捉初次渲染后的更多装载体验,但这些指标很复杂,很难解释,而且通常错误的意思是,当页面的主要内容已经加载时,它们仍然无法识别。

有时候越简单越好。根据w3cwebperformance工作组的讨论和Google的研究,我们发现一个更准确的衡量页面主要内容何时加载的方法是查看最大元素的呈现时间。

最大内容绘制(LCP)度量报告视口中可见的最大图像或文本块的渲染时间。

largest-contentful-paint(LCP)测量加载 性能。为了提供良好的用户体验,LCP应该在页面首次开始加载后的2.5秒内发生。

为了提供良好的用户体验,网站应该努力在页面开始加载的前2.5秒内出现最大的内容绘制。为了确保大多数用户都能达到这一目标,一个很好的衡量标准是页面加载的第75个百分位值,这个值在移动设备和桌面设备上进行了划分。

按照目前在最大内容绘制API中指定的,最大内容绘制所考虑的元素类型为:

  • 元素
  • 在 元素中的元素
  • 元素 (使用海报图像)
  • 具有通过url()函数加载的背景图像的元素(与CSS渐变相反)
  • 包含文本节点或其他内联级别文本元素子级的块级元素。

注意,将元素限制在这个有限的集合中是有意的,以便在开始时保持简单。随着研究的深入,未来可能会添加其他元素(例如,)。

如何确定元素的大小?

为最大内容绘制报告的元素大小通常是用户在视口中可见的大小。如果元素扩展到视口之外,或者任何元素被剪裁或有不可见的溢出,则这些部分不计入元素的大小。

对于已从其内部大小调整大小的图像元素,报告的大小要么是可见大小,要么是内部大小,以较小者为准。例如,缩小到比其固有大小小得多的图像将只报告其显示的大小,而拉伸或扩展到更大尺寸的图像将只报告其内部大小。

对于文本元素,只考虑其文本节点的大小(包含所有文本节点的最小矩形)。

对于所有元素,不考虑通过CSS应用的任何边距、填充或边框。

确定哪些文本节点属于哪些元素有时会很棘手,尤其是对于其子元素包括内联元素和纯文本节点但也包含块级元素的元素。关键是每个文本节点都属于(并且只属于)其最近的块级祖先元素。在规范中:每个文本节点都属于生成其包含块的元素。

largest contentful paint是什么时候报告的

网页通常是分阶段加载的,因此,页面上最大的元素可能会发生变化。

为了处理这种变化的可能性,浏览器在绘制了第一个帧后立即发送一个类型为“largest-contentful-paint”的PerformanceEntry来标识最大的内容元素。但是,在呈现后续帧之后,只要最大的内容元素发生变化,它就会发送另一个PerformanceEntry。

例如,在包含文本和图像的页面上,浏览器最初可能只是呈现文本,此时浏览器将发送一个largest-contentful-paint条目,其element 属性可能引用<p><h1>。稍后,一旦图像完成加载,第二大的内容绘制条目将被调度,其element属性将引用<img>

需要注意的是,元素只有在呈现并对用户可见时才被视为最大的内容元素。尚未加载的图像不被视为“渲染”。在字体块期间,文本节点也不使用web字体。在这种情况下,较小的元素可能被报告为最大的内容元素,但一旦较大的元素完成呈现,它将通过另一个PerformanceEntry对象报告。

除了延迟加载图像和字体之外,当新内容可用时,页面可能会向DOM添加新元素。如果这些新元素中的任何一个比之前最大的内容元素大,则还将报告新的PerformanceEntry。

如果页面从DOM中删除了元素,则不再考虑该元素。类似地,如果一个元素的相关图像资源发生变化(例如,JavaScript改变img.src),然后该元素将停止被考虑,直到新的图像加载。

将来,从DOM中删除的元素仍然可以被视为LCP候选元素。目前正在进行研究,以评估这一变化的影响。您可以跟踪度量更改日志以保持最新。

一旦用户与页面交互(通过轻触、滚动或按键),浏览器将停止报告新条目,因为用户交互经常会改变用户可见的内容(尤其是滚动)。

出于分析目的,您应该只向您的分析服务报告最近调度的性能尝试。

注意:由于用户可以在后台选项卡中打开页面,所以在用户聚焦该选项卡之前,可能不会出现最大的内容绘制,这可能比首次加载该选项卡时要晚得多。

Load time vs. render time

出于安全原因,对于缺少“ Timing-Allow-Origin”标头的跨源图像,不会显示图像的渲染时间戳。相反,只公开它们的加载时间(因为这已经通过许多其他web api公开)。

下面的用法示例显示如何处理呈现时间不可用的元素。但是,如果可能的话,我们总是建议您设置Timing Allow Origin头,这样您的度量将更加准确。

如何处理元素布局和大小更改?

为了使计算和分派新的性能项的性能开销保持在较低水平,对元素大小或位置的更改不会生成新的LCP候选项。只考虑元素在视口中的初始大小和位置。

这意味着最初在屏幕外渲染然后在屏幕上转换的图像可能不会被报告。这也意味着最初在视口中渲染的元素被向下推到视图之外时,仍将报告其初始的视口大小。

但是,(如上所述)如果一个元素从DOM中删除或者其关联的图像资源发生了变化,那么它将从考虑中移除

示例

以下是几个热门网站上出现的Largest Contentful Paint的例子:

在上述两个时间轴中,最大的元素会随着内容加载而变化。在第一个示例中,新内容被添加到DOM中,这会改变哪个元素是最大的。在第二个示例中,布局更改,以前最大的内容将从视口中移除。

虽然延迟加载的内容通常比页面上已有的内容大,但情况并非如此。接下来的两个例子展示了在页面完全加载之前发生的最大的内容绘制

在第一个例子中,Instagram的logo加载得比较早,即使其他内容逐渐显示出来,它仍然是最大的元素。在Google搜索结果页面示例中,最大的元素是在任何图像或徽标加载完成之前显示的文本段落。由于所有单独的图像都比这一段小,所以在整个加载过程中它仍然是最大的元素。

在Instagram时间轴的第一帧中,您可能会注意到相机徽标周围没有绿色方框。这是因为它是一个元素,元素当前不被视为LCP候选元素。第一个LCP候选者是第二帧中的文本。

在JavaScript中测量LCP

测量LCP(以及所有Web Vitals【web关键点】字段指标)的最简单方法是使用Web Vitals JavaScript库,它将手动测量LCP的所有复杂性封装到一个函数中:

import {getLCP} from 'web-vitals';

//测量并记录当前LCP值,
//随时可以报告。
getLCP(console.log);

要手动测量LCP,可以使用Largest Contentful Paint API。以下示例显示如何创建PerformanceObserver,该服务器侦听最大的内容绘制项并将LCP值记录到控制台:

//跟踪页面是否(以及何时)首次隐藏,请参见:

// https://github.com/w3c/page-visibility/issues/29

//注:理想情况下,该检查将在文件<head>中执行

//以避免在运行此代码之前可见性状态发生更改的情况。
let firstHiddenTime = 
document.visibilityState === 'hidden' ? 0 : Infinity;
document.addEventListener('visibilitychange', (event) => {
  firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
}, {once: true});

//将数据发送到终结点。这个代码

//使用“/analytics”;您可以用自己的URL替换它。
function sendToAnalytics(data) {
  const body = JSON.stringify(data);
  //使用`navigator.sendBeacon()`,如果可以的话,失败了返回到 `fetch()`。
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
      fetch('/analytics', {body, method: 'POST', keepalive: true});
}

// 使用try/catch代替特征检测 `largest-contentful-paint`
// 支持,因为有些浏览器在使用新的“type”选项时抛出。
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 创建一个变量来保存最新的LCP值(因为它可以更改)。
  let lcp;

  function updateLCP(entry) {
    //只有在之前页面未隐藏时才包含LCP条目

    //正在发送的条目。这通常发生在页面

    //在背景选项卡中加载。
    if (entry.startTime < firstHiddenTime) {
      //注意:“startTime”值是一个getter,它返回条目的
     //“renderTime”值(如果可用),否则为“loadTime”值。
     //如果元素是图像,则“renderTime”值可能不可用
     //加载的是cross-origin,没有“Timing-Allow-Origin”头。
      lcp = entry.startTime;
    }
  }

  // 创建为每个条目调用“updateLCP”的PerformanceObserver。
  const po = new PerformanceObserver((entryList, po) => {
    entryList.getEntries().forEach((entry) => updateLCP(entry, po));
  });

  //观察“largest-contentful-paint”类型的条目,包括缓冲条目,
//即在调用下面的“observe()”之前发生的条目。
  po.observe({
    type: 'largest-contentful-paint',
    buffered: true,
  });

  //一旦页面的生命周期状态更改为“隐藏”。
  addEventListener('visibilitychange', function fn(event) {
    if (document.visibilityState === 'hidden') {
      removeEventListener('visibilitychange', fn, true);

      //强制调度任何挂起的记录并断开观察者的连接。
      po.takeRecords().forEach((entry) => updateLCP(entry, po));
      po.disconnect();

      //如果设置了LCP,请将其报告给分析端点。
      if (lcp) {
        sendToAnalytics({lcp});
      }
    }
  }, true);
} catch (e) {
  //如果浏览器不支持此API,则不执行任何操作。
}

如果页面是在后台选项卡中加载的,则不应报告LCP。上面的代码部分地解决了这个问题,但是它并不完美,因为页面可能在代码运行之前被隐藏并显示出来。这个问题的解决方案正在[页面可见性API规范]中(https://github.com/w3c/page-visibility/issues/29)讨论

如果最大的元素不是最重要的呢?#

在某些情况下,页面上最重要的元素(或多个元素)与最大的元素不同,开发人员可能更感兴趣的是测量这些其他元素的呈现时间。这可以使用元素计时API实现,如关于定制度量的文章中所述。

如何提高LCP#

LCP主要受四个因素影响:

  • 服务器响应时间慢

  • 呈现阻塞JavaScript和CSS

  • 资源加载时间

  • 客户端渲染

有关如何改进LCP的详细信息,请参阅优化LCP。有关还可以提高LCP的性能技巧的其他指南,请参阅:

第一次输入延迟(First Input Delay, FID)

参考 web.dev/fid/

衡量互动性。为了提供良好的用户体验,页面的FID应该小于100毫秒。

First Input Delay(First Input Delay,FID)是一种重要的、以用户为中心的衡量负载响应性的指标,因为它量化了用户在尝试与无响应页面交互时的体验—低FID有助于确保页面可用。

虽然很难衡量用户有多喜欢使用webapi的网站设计,但衡量其速度和响应能力却不是!

用户对使用first contentful Paint(FCP)可以测量站点加载速度的第一印象。但是你的网站在屏幕上绘制像素的速度只是故事的一部分。同样重要的是,当用户试图与这些像素进行交互时,你的站点的响应速度有多高!

FirstInputDelay(FirstInputDelay,FID)指标有助于测量用户对站点交互性和响应性的第一印象。

什么是FID?#

FID测量从用户第一次与页面交互(即,当用户单击链接、点击按钮或使用自定义的JavaScript驱动控件)到浏览器实际能够开始处理事件处理程序以响应该交互的时间。

一般来说,输入延迟(又称输入延迟)的发生是因为浏览器的主线程正忙于做其他事情,所以它还不能(现在)响应用户。可能发生这种情况的一个常见原因是浏览器忙于解析和执行应用程序加载的大型JavaScript文件。在执行此操作时,它不能运行任何事件侦听器,因为它加载的JavaScript可能会告诉它执行其他操作。

什么是好的FID分数?#

为了提供良好的用户体验,网站应该努力使第一次输入延迟小于100毫秒。为了确保大多数用户都能达到这一目标,一个很好的衡量标准是页面加载的第75个百分位值,这个值在移动设备和桌面设备上进行了划分。

详细的FID

作为编写响应事件的代码的开发人员,我们通常假设一旦事件发生,我们的代码就会立即运行。但作为用户,我们经常会遇到相反的情况:我们在手机上加载网页,尝试与之交互,然后在什么都没发生时感到沮丧。

一般来说,输入延迟(又称输入延迟)的发生是因为浏览器的主线程正忙于做其他事情,所以它还不能(现在)响应用户。可能发生这种情况的一个常见原因是浏览器忙于解析和执行应用程序加载的大型JavaScript文件。在执行此操作时,它不能运行任何事件侦听器,因为它加载的JavaScript可能会告诉它执行其他操作。

抓住了!

FID只测量事件处理中的“延迟”。它不测量事件处理时间本身,也不测量浏览器在运行事件处理程序后更新UI所需的时间。虽然这段时间确实会影响用户体验,但将其作为FID的一部分会激励开发人员异步响应事件,这将改善指标,但可能会使体验变差。请参阅下面的“为什么只考虑输入延迟”以了解更多详细信息。

考虑以下典型网页加载的时间轴: 上面的可视化显示了一个页面,该页面对资源(很可能是CSS和JS文件)发出了两个网络请求,在这些资源下载完成后,在主线程上对它们进行处理。

这会导致主线程暂时处于忙碌状态,这由米色的任务块表示。

长的第一次输入延迟通常发生在第一次内容绘制(FCP)和交互时间(TTI)之间,因为页面已经呈现了一些内容,但还不能可靠地交互。为了说明这是如何发生的,FCP和TTI已添加到时间轴中:

您可能已经注意到FCP和TTI之间有相当长的时间(包括三个长的任务),如果用户在这段时间内尝试与页面交互(例如,单击链接),则在收到单击和主线程能够响应之间会有一段延迟。

考虑一下,如果用户试图在最长任务开始时与页面交互,会发生什么情况:

因为输入发生在浏览器正在运行任务的过程中,它必须等到任务完成后才能对输入做出响应。它必须等待的时间是该用户在此页面上的FID值。

对于站点应该如何修复高的第一次输入延迟(代码分割、预先加载较少的JavaScript等)的建议解决方案,不一定与页面加载后修复缓慢的输入延迟的解决方案相同。通过分离这些指标,我们将能够为web开发人员提供更具体的性能指导。

在这个例子中,用户刚好在主线程最忙的时期开始时与页面交互。如果用户刚才与页面交互(在空闲期间),浏览器可能会立即响应。输入延迟的这种差异强调了在报告指标时查看FID值分布的重要性。

如果交互没有事件侦听器怎么办

FID测量接收到输入事件和主线程下一次空闲之间的增量。这意味着即使在事件侦听器尚未注册的情况下也要测量FID。原因是许多用户交互不需要事件侦听器,但需要主线程处于空闲状态才能运行。

例如,在响应用户交互之前,以下所有本机HTML元素都需要等待主线程上正在进行的任务完成:

  • 文本字段、复选框和单选按钮(<input>,<textarea>

  • 选择下拉列表(<Select>

  • 链接(<a>

为什么只考虑第一个输入?

虽然任何输入的延迟都可能导致不良的用户体验,但我们主要建议测量第一次输入延迟,原因如下:

  • 第一次输入延迟将是用户对网站响应能力的第一印象,而第一印象对于塑造我们对网站质量和可靠性的总体印象至关重要。

  • 我们今天在网络上看到的最大的交互性问题发生在页面加载过程中。因此,我们相信最初专注于改进网站的第一次用户交互将对提高网站的整体交互性产生最大的影响。

  • 对于站点应该如何修复高的第一次输入延迟(代码分割、预先加载较少的JavaScript等)的建议解决方案,不一定与页面加载后修复缓慢的输入延迟的解决方案相同。通过分离这些指标,我们将能够为web开发人员提供更具体的性能指导。

什么算第一次输入?#

FID是一种度量页面在加载期间的响应能力的度量。因此,它只关注离散动作(如单击、点击和按键)的输入事件。

其他交互,如滚动和缩放,是连续的操作,具有完全不同的性能约束(而且,浏览器通常能够通过在单独的线程上运行来隐藏延迟)。

换言之,FID侧重于轨道性能模型中的R(响应性),而滚动和缩放更多地与A(动画)相关,它们的性能质量应单独评估。

如果一个用户从未与你的站点交互呢?

不是所有的用户每次访问你的网站时都会与他们互动。并不是所有的交互都与FID相关(如前一节所述)。另外,有些用户的第一次交互会在不好的时候(当主线程很长一段时间很忙的时候),有些用户的第一次交互会在好的时候(当主线程完全空闲的时候)。

这意味着有些用户没有FID值,有些用户FID值较低,有些用户可能具有较高的FID值。

您如何跟踪、报告和分析FID可能与您习惯使用的其他指标有很大不同。下一节将解释如何最好地做到这一点。

为什么只考虑输入延迟?

如上所述,FID仅测量事件处理中的“延迟”。它不测量事件处理时间本身,也不测量浏览器在运行事件处理程序后更新UI所需的时间。

尽管这段时间对用户来说很重要,并且确实会影响用户的体验,但它不包括在这个指标中,因为这样做可能会激励开发人员增加工作区,从而使体验变得更糟,也就是说,它们可以将事件处理程序逻辑包装在异步回调中(通过setTimeout()或requestAnimationFrame()),以便将其与与事件关联的任务分开。其结果将是度量分数的提高,但用户感知到的响应较慢。

然而,虽然FID只测量事件延迟的“延迟”部分,但是想要跟踪更多事件生命周期的开发人员可以使用事件计时API来完成。有关详细信息,请参阅自定义指标指南。

交互时间(Time to Interactive, TTI)

交互时间(TTI)是衡量负载响应性的重要实验室指标。它有助于识别页面看起来是交互式的,但实际上不是交互的。快速TTI有助于确保页面是可用的。

TTI度量度量从页面开始加载到其主要子资源已加载的时间,并且能够可靠地快速响应用户输入。

要根据网页的性能跟踪计算TTI,请执行以下步骤:

  • First Contentful Paint (FCP).

  • 在时间上向前搜索一个至少5秒的安静窗口,其中安静窗口的定义是:没有长任务和不超过两个在飞行中的网络GET请求。

  • 向后搜索安静窗口之前的最后一个长任务,如果没有找到长任务,则在FCP处停止。

  • 如果任务的结束时间与fctti的最后一个时间窗口的值相同,则为long。

下图有助于将上述步骤可视化:

从历史上看,开发人员已经为快速呈现时间优化了页面,有时是以TTI为代价的。

像服务器端呈现(SSR)这样的技术可能会导致页面看起来是交互式的(也就是说,链接和按钮在屏幕上是可见的),但实际上它并不是交互式的,因为主线程被阻止了,或者因为控制这些元素的JavaScript代码没有加载。

当用户试图与一个看似互动但实际上并非如此的页面进行交互时,他们可能会以以下两种方式之一进行响应:

  • 在最好的情况下,他们会因为页面响应慢而感到恼火。

  • 在最坏的情况下,他们会假设页面已损坏并可能离开。他们甚至可能对你的品牌价值失去信心或信任。

    为了避免这个问题,尽一切努力使FCP和TTI之间的差异最小化。如果确实存在明显的差异,请通过视觉指示器清楚地表明页面上的组件还没有交互。

    为了提供良好的用户体验,当在平均的移动硬件上进行测试时,网站应该力争有少于5秒的交互时间。

有关页面的TTI如何影响Lighthouse性能分数的详细信息,请参阅Lighthouse如何确定TTI分数

总阻塞时间(Total Blocking Time, TBT)

总阻塞时间(TBT)是衡量负载响应性的一个重要实验室指标,因为它有助于量化页面在变得可靠交互之前的严重程度—低TBT有助于确保页面可用。

total blocking time(TBT)度量度量第一个内容绘制(FCP)和交互时间(TTI)之间的总时间量,其中主线程被阻塞的时间足够长,以阻止输入响应。

只要有一个长任务(在主线程上运行超过50毫秒)的任务,主线程就被认为是“阻塞的”。我们说主线程被“阻塞”是因为浏览器无法中断正在进行的任务。因此,如果用户确实在长任务中与页面交互,浏览器必须等待任务完成后才能响应。

如果任务足够长(例如超过50毫秒),用户很可能会注意到延迟,并认为页面迟钝或刺耳。

给定长任务的阻塞时间是其超过50ms的持续时间,页的总阻塞时间是FCP和TTI之间发生的每个长任务的阻塞时间之和。

例如,考虑在页面加载过程中浏览器主线程的下图: 上面的时间线有五个任务,其中三个是长任务,因为它们的持续时间超过50毫秒。下一个图表显示了每个长任务的阻塞时间: 因此,虽然在主线程上运行任务的总时间是560毫秒,但只有345毫秒被认为是阻塞时间。

TBT是TTI的一个很好的配套指标,因为它有助于量化页面在变得可靠交互之前的严重程度。

如果主线程在至少5秒钟内没有长任务,TTI认为页面是“可靠交互的”。这意味着,在10秒内分散的3个51ms任务可以将TTI向后推到一个10秒长的任务,但是对于试图与页面交互的用户来说,这两个场景会感觉非常不同。

在第一种情况下,3个51毫秒的任务的TBT为3毫秒,而单个10秒长的任务的TBT为9950毫秒。第二种情况下TBT值越大,表示体验越差。

为了提供良好的用户体验,当在平均移动硬件上进行测试时,站点应该努力使总阻塞时间小于300毫秒。

有关页面的TBT如何影响灯塔性能得分的详细信息,请参阅Lighthouse如何确定TBT得分

累计布局偏移(Cumulative Layout Shift, CLS):

参考:web.dev/cls/

测量视觉稳定性。为了提供良好的用户体验,页面应该维护小于0.1的CLS。

累积布局偏移(CLS)是一个重要的、以用户为中心的度量标准,用于测量视觉稳定性,因为它有助于量化用户体验意外布局变化的频率—低CLS有助于确保页面令人愉快。

你是否曾经在网上读过一篇文章,突然页面上出现了变化?如果没有警告,文字就会移动,你就失去了位置。或者更糟的是:你要点击一个链接或一个按钮,但是在你的手指落地前,链接移动了,你最后点击了其他东西!

大多数时候,这类经历只是令人讨厌,但在某些情况下,它们会造成真正的损害。

页面内容的意外移动通常会发生,因为资源是异步加载的,或者DOM元素在现有内容之上被动态添加到页面中。罪魁祸首可能是尺寸未知的图像或视频,呈现比其备用大小更大或更小的字体,或者动态调整自身大小的第三方广告或小部件。

使这个问题更加棘手的是,一个站点在开发中的功能通常与用户的体验有很大的不同。个性化或第三方内容在开发中的行为通常与生产中的不同,测试图像通常已经在开发人员的浏览器缓存中,并且在本地运行的API调用通常非常快,因此延迟并不明显。

累积布局移位(CLS)度量通过度量实际用户发生这种情况的频率来帮助您解决这个问题。

CLS测量在页面的整个生命周期内发生的每个意外布局移位的所有单独布局移位分数的总和。

当可见元素的位置从一个渲染帧更改到下一个渲染帧时,就会发生布局偏移。(有关如何计算单个版面轮班分数的详细信息,请参见下文。)

为了提供良好的用户体验,网站应努力使CLS得分低于0.1。为了确保大多数用户都能达到这一目标,一个很好的衡量标准是页面加载的第75个百分位值,这个值在移动设备和桌面设备上进行了划分。

测量指标

用于测量和报告核心网络关键点的工具

谷歌认为,网络核心要素对所有网络体验至关重要。因此,它致力于在其所有流行的工具中呈现这些指标。以下部分详细介绍了哪些工具支持核心Web关键点。

现场工具,以测量核心网络关键点

Chrome用户体验报告收集匿名的,真实的用户测量数据,每个核心网络至关重要。这些数据使网站所有者能够快速评估他们的性能,而不需要他们在他们的页面上手动进行分析,并支持像PageSpeed Insights和搜索控制台的核心网络关键点报告这样的工具。

有关如何使用这些工具的指导,以及哪个工具适合您的用例,请参阅:开始测量Web关键点

Chrome用户体验报告提供的数据提供了一种快速评估站点性能的方法,但它没有提供精确诊断、监控和快速响应回归所需的详细的、按页面查看的遥测数据。因此,我们强烈建议网站建立自己的真实用户监控。

用JavaScript测量核心Web关键点

可以使用标准的web api在JavaScript中测量每个核心Web关键点。

衡量所有核心Web关键点的最简单方法是使用Web Vitals JavaScript库,这是一个小型的、可用于生产的包装器,它围绕着底层的Web api,以精确匹配上面列出的所有Google工具的报告方式来衡量每个指标。

使用web vitals库,测量每个指标就像调用单个函数一样简单(有关完整用法API详细信息,请参阅文档):

import {getCLS, getFID, getLCP} from 'web-vitals';

function sendToAnalytics(metric) {
  const body = JSON.stringify(metric);
  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
      fetch('/analytics', {body, method: 'POST', keepalive: true});
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);

您还可以报告每个核心的Web关键点,使用Web Vitals Chrome扩展而无需编写任何代码。这个扩展使用web vitals库来度量这些度量,并在用户浏览web时显示给他们。

此扩展有助于了解您自己的站点、竞争对手的站点以及整个web的性能。

或者,喜欢通过底层web api直接度量这些度量的开发人员可以参考这些度量指南了解实现细节:

有关如何使用流行的分析服务(或您自己的内部分析工具)测量这些指标的其他指导,请参阅:现场测量Web关键点的最佳实践

测量核心网络生命体征的实验室工具

虽然所有的核心网络关键点,首先和最重要的,是现场指标,其中许多也是可测量的实验室。

在特性发布给用户之前,实验室测量是在开发期间测试特性性能的最佳方法。这也是在性能退化发生之前捕捉它们的最佳方法。

以下工具可用于在实验室环境中测量核心网络关键点:

像Lighthouse这样的工具在没有用户的情况下在模拟环境中加载页面,无法测量FID(没有用户输入)。然而,总阻塞时间(TBT)指标是实验室可测量的,是FID的一个很好的代表。在实验室中改善TBT的性能优化应能改善现场FID(见下面的性能建议)。

虽然实验室测量是提供伟大经验的重要组成部分,但它不能代替现场测量。

根据用户的设备功能、网络状况、设备上可能正在运行的其他进程以及它们如何与页面交互,站点的性能可能会有很大的变化。事实上,每个核心的Web关键指标的得分都会受到用户交互的影响。只有实地测量才能准确地捕捉到完整的图像。

提高分数的建议

一旦你测量了网络的核心要素并确定了需要改进的地方,下一步就是优化。以下指南为如何针对每个核心Web关键点优化页面提供了具体建议:

其他网络关键点

虽然核心Web关键点是理解和交付优秀用户体验的关键指标,但还有其他重要指标。

这些其他的Web关键点通常作为核心Web关键点的代理或补充指标,以帮助捕获更多的体验或帮助诊断特定问题。

例如,度量第一个字节的时间(TTFB)第一个内容绘制(FCP)都是加载体验的重要方面,在诊断LCP(分别是服务器响应时间慢或呈现阻塞资源)问题时都很有用。

类似地,诸如总阻塞时间(TBT)交互时间(TTI)等指标是实验室指标,对于捕捉和诊断影响FID的潜在交互问题至关重要。然而,它们不是核心Web关键点集的一部分,因为它们不可现场测量,也不反映以用户为中心的结果

不断发展的网络生命

Web关键点和核心Web关键点代表了开发人员今天用来衡量整个Web体验质量的最佳可用信号,但这些信号并不完美,应该期待将来的改进或添加。

核心的网络关键点与所有网页相关,并在相关的谷歌工具中呈现。对这些指标的更改将产生广泛的影响;因此,开发人员应该期望核心Web关键点的定义和阈值是稳定的,并且更新需要事先通知和可预测的年度节奏。

其他Web关键点通常是上下文或工具特定的,可能比核心Web关键点更具实验性。因此,它们的定义和阈值可能会更频繁地改变。

对于所有的Web关键点,更改将清楚地记录在这个公共变更日志中。

其他

  • first contentful paint(FCP):1s以内。首次内容绘制 FCP测量用户导航到页面后浏览器呈现第一段DOM内容所需的时间。页面上的图像、非白色元素和svg都被视为DOM内容;iframe中的任何内容都不包括在内。

  • first cpu idle(FCI):50ms以内。注意:在Lighthouse6.0中不推荐使用第一个CPU空闲。虽然有人发现第一个CPU空闲时间比交互时间提供了更有意义的度量,但是这种差异并不显著,不足以证明维护两个相似的度量标准的合理性。向前看,考虑使用总阻塞时间和时间来进行交互。一般在50毫秒以内。

  • interactive(TTI):少于5s。交互时间(TTI)是衡量负载响应性的重要实验室指标。它有助于识别页面看起来是交互式的,但实际上不是交互的。快速TTI有助于确保页面是可用的。TTI度量度量从页面开始加载到其主要子资源已加载的时间,并且能够可靠地快速响应用户输入。要根据网页的性能跟踪计算TTI,请执行以下步骤:1、先从 First Contentful Paint (FCP)开始。2、在时间上向前搜索一个至少5秒的安静窗口,其中安静窗口的定义是:没有长任务和不超过两个在飞行中的网络GET请求。 3、向后搜索安静窗口之前的最后一个长任务,如果没有找到长任务,则在FCP处停止。4、TTI是安静窗口之前最后一个长任务的结束时间(如果没有找到长任务,则与FCP值相同)。下图有助于将上述步骤可视化:

  • first meaningful paint(FMP):3S以内。Lighthouse 6.0中不推荐使用First Meaningful Paint (FMP)。在实践中,FMP对页面加载的微小差异过于敏感,导致结果不一致(双峰)。此外,该指标的定义依赖于特定于浏览器的实现细节,这意味着它既不能标准化,也不能在所有web浏览器中实现。向前看,考虑使用 Largest Contentful Paint替换。FMP度量页面的主要内容何时对用户可见。FMP的原始分数是用户启动页面加载和页面呈现折叠内容上方的主页面之间的时间(以秒为单位)。FMP基本上显示了绘制的时间,在此之后,折叠上方的布局发生了最大的变化

  • max potential fid:最大潜在FID测量用户可能遇到的最坏情况下的第一次输入延迟。Lighthouse计算最大潜在的FID通过找到最长的任务在First Contentful Paint (FCP)后的持续时间First Contentful Paint (FCP)之前的任务被排除在外,因为用户不太可能在任何内容呈现到屏幕之前尝试与页面交互,而这正是First Contentful Paint衡量的。

  • estimated input latency(EIL):50ms以内。估计输入延迟是指在页面加载最忙的5秒窗口期间,应用程序响应用户输入所需的时间。这个审计的时间是从第一次有意义的绘制到跟踪的结束,这大约是5秒之后的交互时间。如果你的延迟超过50毫秒,用户可能会认为你的应用程序滞后。

  • total blocking time(TBT):小于300ms。度量第一个内容绘制(FCP)和交互时间(TTI)之间的总时间量,其中主线程被阻塞的时间足够长,以阻止输入响应。 只要有一个长任务(在主线程上运行超过50毫秒)的任务,主线程就被认为是“阻塞的”。我们说主线程被“阻塞”是因为浏览器无法中断正在进行的任务。因此,如果用户确实在长任务中与页面交互,浏览器必须等待任务完成后才能响应。 如果任务足够长(例如超过50毫秒),用户很可能会注意到延迟,并认为页面迟钝或刺耳。 给定长任务的阻塞时间是其超过50ms的持续时间,页的总阻塞时间是FCP和TTI之间发生的每个长任务的阻塞时间之和。

  • speed index(SI):小于3s。速度索引衡量内容在页面加载期间的可视化显示速度。Lighthouse首先在浏览器中捕获页面加载的视频,并计算帧之间的视觉进度。然后Lighthouse使用 Speedline Node.js module 生成速度指数得分。

  • cumulative layout shift(CLS):衡量视觉稳定性,为了提供良好的用户体验,页面的CLS应保持小于 0.1。

  • First Input Delay (FID): 衡量可交互性,为了提供良好的用户体验,页面的 FID 应当小于 100毫秒。

以上关于指标数据非标准数据,请根据lighthouse/scorecalc进行计算