尝试衡量软导航

自推出以来,Core Web Vitals 计划一直致力于衡量网站的实际用户体验,而不是衡量网站创建或加载方式背后的技术细节。这三个 Core Web Vitals 指标被创建为以用户为中心的指标,这是相对于现有技术指标(例如 DOMContentLoadedload)的演变,用于衡量的时间通常与用户对网页性能的看法无关。因此,用于构建网站的技术不会影响评分,也不会影响网站性能。

现实总是比理想情况更加棘手,热门的单页应用架构从未受到核心网页指标的全面支持。这些 Web 应用不是在用户浏览网站时加载各自独立的网页,而是采用所谓的“软导航”,即通过 JavaScript 更改网页内容。在这些应用中,通过更改网址并推送浏览器历史记录中之前的网址,从而保持常规网页架构的假象,从而使后退和前进按钮能够按照用户预期的方式工作。

许多 JavaScript 框架都使用此模型,但每种框架都以不同的方式使用。这超出了浏览器传统理解为“网页”的范围,因此衡量这一点一直困难重重:当前网页的互动与当前网页的互动之间要划定界限,还是要将其视为新网页?

Chrome 团队一直在考虑这一挑战,并且正在寻求对什么是“软导航”的定义进行标准化,以及如何针对这一问题衡量核心网页指标,采用的衡量方式与衡量采用传统多页架构 (MPA) 的网站的方式类似。虽然这些实施仍处于早期阶段,但该团队现在已准备好向更多网站提供已实施的内容,以供其开展实验。这将允许网站就到目前为止的方法提供反馈。

什么是软导航?

我们已提出了以下对“软导航”的定义:

  • 导航由用户操作启动。
  • 导航会向用户显示可见的网址更改,并更改历史记录。
  • 导航会导致 DOM 更改。

对于某些网站,这些启发式方法可能会导致误报(用户不会真正认为发生了“导航”)或漏报(即使不符合这些条件,用户仍认为进行了一次“导航”)。欢迎在软导航规范代码库中提供关于启发法的反馈。

Chrome 如何实现软导航?

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

完成这些更改后,系统就可以针对每次网页导航衡量 Core Web Vitals 指标以及一些相关的诊断指标,但需要考虑一些细微差别。

在 Chrome 中启用软导航有什么影响?

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

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

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

如何在 Chrome 中启用软导航?

默认情况下,Chrome 不会启用软导航功能。不过,从 Chrome 110 开始,用户只要明确启用此功能即可进行实验。

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

如果某网站希望为所有访问者启用此功能,以了解其影响,可以从 Chrome 117 开始运行源试用,只需注册试用,并在 HTML 或 HTTP 标头中添加带有源试用令牌的元元素即可。如需了解详情,请参阅开始试用源试用一文。

网站所有者可以选择在其网页上为所有用户或仅为部分用户提供源试用。请注意上文中的“影响”部分,了解这会如何改变指标的报告方式,尤其是在面向大部分用户启用此源试用的情况下。请注意,无论此软导航设置如何,CrUX 都将继续以现有方式报告指标,因此不受这些影响的影响。另请注意,源试用也仅限于在 14 天内,以所有 Chrome 网页加载的 0.5% 为中位数启用实验性功能,但这应该只是对于超大型网站才是问题。

如何衡量软导航?

启用软导航实验后,系统会照常使用 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)的基准。

按软导航衡量核心网页指标

如需包含软导航指标条目,您需要在 Performance Observer 的 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 目前,web-vitals 库仅报告该网页的第一个 FCP。
LCP 相对于软导航开始时间的下一个最大 Contentful Paint 的时间。不考虑上一个导航中的现有渲染。因此,LCP 将 >= 0。与往常一样,系统会在发生互动或网页在后台运行时报告此问题,因为只有这样,LCP 才能最终确定。
CLS 导航时间之间的最大偏移窗口。和往常一样,当网页在后台运行时,CLS 才能最终确定。如果没有偏移,则报告 0 值。
INP 导航时间之间的 INP。像往常一样,报告会在发生互动时报告;或者,当网页在后台运行时,系统才会报告 INP。如果没有互动,则不报告值为 0。

这些更改会纳入到核心网页指标衡量中吗?

这个软导航实验就是一个实验。在决定是否将其整合到核心网页指标计划中之前,我们需要评估启发词语,看看它们是否能够更准确地反映用户体验。我们非常高兴能够进行这种实验,但无法保证这是否或何时会取代当前的测量方法。

我们重视 Web 开发者对实验的反馈、所使用的启发法,以及您是否认为这些反馈能够更准确地反映体验。软导航 GitHub 代码库是提供此类反馈的最佳场所,不过,您可以在 Chrome 问题跟踪器中报告 Chrome 实现过程中出现的具体 bug。

如何在 CrUX 中报告软导航?

此实验成功后,CrUX 将如何报告软导航的确切情况也待定。我们不一定会像对待当前的“硬”导航一样对待它们。

在某些网页中,就用户而言,软导航几乎等同于整个网页加载,单页应用技术的使用只是一个实现细节。在其他情况下,它们可能更类似于包含部分附加内容。

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

目前,该团队正专注于启发式方法和技术实施,这将让我们能够评判这项实验的成效,因此未在这方面做出任何决定。

反馈

我们正在积极征求以下各方关于此实验的反馈:

更新日志

由于此 API 尚处于实验阶段,因此会进行很多更改,这些更改比使用稳定版 API 更重要。如需了解详情,请参阅 Soft Navigation Heuristics 更新日志

总结

软导航实验是一种激动人心的方法,它展示了 Core Web Vitals 计划可能会如何演变,以衡量现代 Web 上的一种常见模式,而目前我们的指标中尚未出现该模式。虽然这项实验尚处于早期阶段,还有很多工作要做,但让更广泛的网络社区可以继续进行相关实验是非常重要的一步。收集这项实验的反馈是实验的另一个重要环节,因此我们强烈建议对这项开发感兴趣的人利用这次机会来帮助改进该 API,确保它代表我们希望通过测试进行衡量的内容。

致谢

Jordan Madrid 提供的 Unsplash 缩略图