尝试衡量软导航

自推出以来,“核心网页指标”计划一直致力于衡量网站的实际用户体验,而不是衡量网站创建或加载方式背后的技术细节。Core Web Vitals 的三个指标是作为以用户为中心的指标而创建的,这是在 DOMContentLoadedload 等现有技术指标的基础上演变的,这些指标衡量的时间通常与用户对网页性能的看法无关。因此,构建网站所用的技术不会影响网站表现良好的评分。

实际情况总是比理想情况复杂一点,而热门的单页应用架构从未得到 Core Web Vitals 指标的全面支持。这些网络应用不是在用户浏览网站时加载不同的具体网页,而是使用所谓的“软导航”,通过 JavaScript 更改网页内容。在这些应用中,通过更改网址并在浏览器历史记录中推送之前的网址来维持传统网页架构的假象,以使后退和前进按钮按用户预期的方式工作。

许多 JavaScript 框架都使用此模型,但每种框架采用的方式有所不同。由于这超出了浏览器传统所理解的“网页”的范围,因此一直很难衡量这一点:要在当前网页上的哪个互动之间画出界限,而不是将其视作一个新网页?

Chrome 团队一直在考虑这一挑战,他们希望对什么是“软导航”的定义进行标准化,并就如何衡量核心网页指标对此进行标准化 - 采用与在传统多页面架构 (MPA) 中实现的网站的衡量方式类似。虽然仍处于早期阶段,但该团队已准备好让更多网站进行实验。这将允许网站就目前的方法提供反馈。

什么是软导航?

我们提出了以下关于软导航的定义:

  • 导航由用户操作启动。
  • 这种导航会使用户看到网址发生变化,并且历史记录也会发生变化。
  • 导航会导致 DOM 更改。

对于某些网站,这些启发词语可能会导致误报(用户不会真正认为发生了“导航”)或误报(即使不符合这些条件,用户确实认为发生了“导航”)。欢迎访问软导航规范库,提供有关启发词语的反馈。

Chrome 如何实现软导航?

启用软导航启发式算法后(下一部分将对此进行详细介绍),Chrome 将更改其报告某些性能指标的方式:

这些更改将允许系统按网页导航来衡量 Core Web Vitals 以及一些相关的诊断指标,但还存在一些需要考虑的细微差别。

在 Chrome 中启用软导航会产生什么影响?

以下是网站所有者在启用此功能后需要考虑的一些变化:

  • 系统可能会针对软导航重新发出其他 FP、FCP 和 LCP 事件。Chrome 用户体验报告 (CrUX) 会忽略这些额外的值,但这可能会影响您网站上的所有实时用户衡量 (RUM) 监测。如果您对这是否会影响相关衡量结果有任何疑问,请与您的 RUM 提供商联系。请参阅“衡量软导航的 Core Web Vitals”部分
  • 在应用代码中使用这些条目时,您可能需要考虑性能条目中新的(可选)navigationID 属性。
  • 只有基于 Chromium 的浏览器才支持这一新模式。虽然许多较新的指标仅在基于 Chromium 的浏览器中提供,但某些指标(FCP、LCP)适用于其他浏览器,因此并非所有人都升级到基于 Chromium 的浏览器的最新版本。因此请注意,某些用户可能不会报告软导航指标。
  • 这是一项实验性的新功能,默认情况下不会启用,网站应测试此功能,以确保不会产生任何其他意外的副作用。

如需详细了解如何衡量软导航指标,请参阅“按软导航衡量核心网页指标”部分

如何在 Chrome 中启用软导航?

Chrome 默认未启用软导航,但您可通过明确启用此功能进行实验。

对于开发者,可通过以下方式启用此功能:在 chrome://flags/#enable-experimental-web-platform-features 中开启实验性网络平台功能标志,或在启动 Chrome 时使用 --enable-experimental-web-platform-features 命令行参数。

如何衡量软导航?

软导航实验启用后,系统将照常使用 PerformanceObserver API 报告指标。不过,对于这些指标,还需要考虑一些额外的注意事项。

报告软导航

您可以使用 PerformanceObserver 观察软导航。下面的示例代码段会将软导航条目记录到控制台,包括此页面上之前使用 buffered 选项进行的软导航:

const observer = new PerformanceObserver(console.log);
observer.observe({ type: "soft-navigation", buffered: true });

此属性可用于最终确定上一次导航中的完整页面指标。

根据相应网址报告指标

由于软导航只有在发生后才能看到,因此某些指标需要在此事件后最终确定,然后再针对之前的网址生成报告,因为当前网址现在将反映新页面更新后的网址。

您可以使用相应 PerformanceEntrynavigationId 属性将事件与正确的网址关联。可以使用 PerformanceEntry API 进行查询:

const softNavEntry =
  performance.getEntriesByType('soft-navigation').filter(
    (entry) => entry.navigationId === navigationId
  )[0];
const hardNavEntry = performance.getEntriesByType('navigation')[0];
const navEntry = softNavEntry || hardNavEntry;
const pageUrl = navEntry?.name;

pageUrl 应该用于根据正确的网址(而不是过去可能使用过的当前网址)报告指标。

获取软导航的 startTime

导航开始时间可通过以下类似方式获取:

const softNavEntry =
  performance.getEntriesByType('soft-navigation').filter(
    (entry) => entry.navigationId === navigationId
  )[0];
const hardNavEntry = performance.getEntriesByType('navigation')[0];
const navEntry = softNavEntry || hardNavEntry;
const startTime = navEntry?.startTime;

startTime 是启动软导航的初始互动(例如点击按钮)的时间。

所有性能耗时(包括软导航的那些时间)都是从最初的“困难”导航开始的网页导航时间。因此,软导航开始时间需要作为软导航加载指标时间(例如 LCP)的基准(相对于此软导航时间)。

衡量每次软导航的核心网页指标

如需添加软导航指标条目,您需要在性能观察器的 observe 调用中添加 includeSoftNavigationObservations: true

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('Layout Shift time:', entry);
  }
}).observe({type: 'layout-shift', buffered: true, includeSoftNavigationObservations: true});

除了在 Chrome 中启用软导航功能外,还需要为 observe 方法添加额外的 includeSoftNavigationObservations 标志。在性能观察器级别明确选择启用这一功能是为了确保现有的性能观察者不会对这些额外的条目感到惊讶,因为在尝试衡量核心网页指标以进行软导航时,需要考虑一些其他注意事项。

计时仍会相对于原始“困难”返回导航开始时间。因此,要计算软导航的 LCP 时间,您需要取 LCP 时间并减去适当的软导航开始时间(如前所述),以获得相对于软导航的时间。例如,对于 LCP:

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    const softNavEntry =
      performance.getEntriesByType('soft-navigation').filter(
        (navEntry) => navEntry.navigationId === entry.navigationId
      )[0];
    const hardNavEntry = performance.getEntriesByType('navigation')[0];
    const navEntry = softNavEntry || hardNavEntry;
    const startTime = navEntry?.startTime;
    console.log('LCP time:', entry.startTime - startTime);
  }
}).observe({type: 'largest-contentful-paint', buffered: true, includeSoftNavigationObservations: true});

有些指标历来都是在网页的整个生命周期内进行衡量:例如,LCP 会发生变化,直到发生互动。CLS 和 INP 可以更新,直到用户离开页面为止。因此,每次“导航”(包括原始导航)可能需要在每次发生新的软导航时确定上一页的指标。这意味着初始的“困难”导航指标可能会比平常更早地最终确定。

同样,在开始衡量这些长期指标的新软导航的指标时,需要“重置”指标或“重新初始化”并且被视为新指标,并且不记录为之前的“网页”设置的值。

应如何处理在导航之间保持不变的内容?

软导航的 FP、FCP 和 LCP 将仅衡量新绘制。这可能会导致不同的 LCP,例如从软导航的冷加载变为软加载。

例如,假设某个网页包含一幅作为 LCP 元素的大横幅图片,但该图片下方的文字会随着每次软导航而发生变化。初始网页加载会将横幅图片标记为 LCP 元素,并以此为基础确定 LCP 时间。对于后续的软导航,其下方的文本将是软导航完成后绘制的最大元素,并且将成为新的 LCP 元素。不过,如果某个新页面通过深层链接加载到软导航网址中,则该横幅图片将是新的绘制,因此可以被视为 LCP 元素。

如本例所示,根据网页的加载方式,软导航的 LCP 元素报告方式可能不同,就像加载带有锚链接的网页一样,会导致不同的 LCP 元素。

如何衡量 TTFB?

常规网页加载的首字节时间 (TTFB) 表示返回原始请求的第一个字节的时间。

对于软导航,这个问题比较棘手。我们是否应该衡量针对新网页发出的第一次请求?如果应用中已存在所有内容,并且没有其他请求,该怎么办?如果通过预提取提前发出该请求,会发生什么情况?如果某个请求与软导航无关(例如,属于分析请求),该怎么办?

更简单的方式是将软导航的 TTFB 报告为 0,这与我们为往返缓存恢复所建议采用的方式类似。这是 web-vitals用于软导航的方法。

未来,我们可能会支持使用更精确的方法获悉哪个请求是软导航的“导航请求”并且能够获得更精确的 TTFB 测量结果但这不属于当前实验的一部分。

如何同时衡量新老客户?

在此实验期间,建议继续根据“硬性”指标以当前方式衡量核心网页指标网页导航,与 CrUX 将作为 Core Web Vitals 计划的官方数据集进行衡量和报告的数据保持一致。

除此以外,还应衡量软导航,以便您了解未来可能会如何衡量这些标准,并有机会向 Chrome 团队提供反馈,了解此实现方案的实际运行情况。这将有助于您和 Chrome 团队今后更好地设定 API。

若要衡量这两者,您需要了解软导航模式下可能会发出的新事件(例如,多个 FCP 事件和额外的 LCP 事件),并在适当的时间最终确定这些指标,同时忽略将来仅适用于软导航的事件,从而妥善处理这些事件。

使用 web-vitals 库衡量软导航的核心网页指标

考虑到所有细微差别,最简单的方法是使用 web-vitals JavaScript 库,该库在单独的 soft-navs branch(也可在 npmunpkg 上提供)中对软导航提供实验性支持。这可以通过以下方式进行衡量(根据需要替换 doTraditionalProcessingdoSoftNavProcessing):

import {
  onTTFB,
  onFCP,
  onLCP,
  onCLS,
  onINP,
} from 'https://unpkg.com/web-vitals@soft-navs/dist/web-vitals.js?module';

onTTFB(doTraditionalProcessing);
onFCP(doTraditionalProcessing);
onLCP(doTraditionalProcessing);
onCLS(doTraditionalProcessing);
onINP(doTraditionalProcessing);

onTTFB(doSoftNavProcessing, {reportSoftNavs: true});
onFCP(doSoftNavProcessing, {reportSoftNavs: true});
onLCP(doSoftNavProcessing, {reportSoftNavs: true});
onCLS(doSoftNavProcessing, {reportSoftNavs: true});
onINP(doSoftNavProcessing, {reportSoftNavs: true});

确保针对正确的网址报告指标(如前所述)。

web-vitals 库会针对软导航报告以下指标:

指标 详细信息
TTFB 报告为 0。
首次内容渲染 (FCP) 系统只会报告网页的首次 FCP。
LCP 下一个最大内容渲染的时间(相对于软导航开始时间)。系统不会考虑上一个导航中存在的现有绘制。因此,LCP 将 >= 0。与往常一样,系统会在发生互动时或网页在后台运行时报告此问题,因为只有这样才能最终确定 LCP。
CLS 导航时间之间的最大偏移窗口。像往常一样,当网页在后台运行时,只有这样才能最终确定 CLS。如果没有偏移,系统会报告 0 值。
INP 导航时间之间的 INP。与往常一样,系统会在发生互动时或网页在后台运行时报告此情况,因为只有这样,INP 才能最终确定。没有互动时不报告 0 值。

这些变化会纳入到 Core Web Vitals 的衡量范围内吗?

这项软导航实验就是一个实验。我们希望先评估启发法,看看它们能否更准确地反映用户体验,然后再决定是否要将其集成到 Core Web Vitals 计划中。我们非常高兴能够进行这项实验,但无法保证这项实验是否会取代当前的测量结果或何时。

我们非常重视网络开发者以及你认为实验是否能够更准确地反映体验,以及对实验的反馈。软导航 GitHub 代码库是提供这类反馈的最佳途径,不过 Chrome 的实现过程中的每个错误都应在 Chrome 问题跟踪器中报告。

如何在 CrUX 中报告软导航?

如果实验成功,系统如何在 CrUX 中报告软导航的具体方式,这还有待确定。这并不一定意味着它们会被视为与当前的“硬性”级别导航。

就用户而言,在某些网页中,软导航与整个网页加载几乎完全相同,单页应用技术的使用只是实现细节。在其他情况下,响应类型可能更接近于只加载部分额外内容。

因此,我们可能会决定在 CrUX 中单独报告这些软导航,或者在计算指定网页或一组网页的核心网页指标时对其加权。随着启发式算法的改进,我们还可以完全排除部分加载软导航。

该团队专注于启发式技术和技术实现,以便我们评估这项实验的成效,因此尚未就这些方面做出决策。

反馈

我们正在积极征求有关此实验的反馈,希望您能在以下方面积极提供反馈:

更新日志

此 API 正处于实验阶段,因此发生了许多变化,这比使用稳定版 API 时要多。如需了解详情,请参阅软导航启发词语更新日志

总结

软导航实验是一种令人兴奋的方法,有助于核心网页指标计划如何发展,以衡量现代网络上我们的指标中缺少的常见模式。尽管这项实验尚处于早期阶段,但仍有许多工作要做,但将迄今为止的进展提供给更广泛的网络社区进行实验是非常重要的一步。从此实验中收集反馈是实验的另一个重要环节,因此我们强烈建议对此开发成果感兴趣的人利用以下机会来帮助打造该 API,确保它代表了我们希望通过这项技术衡量的成果。

致谢

Jordan MadridUnsplash 活动中的缩略图图片