尝试衡量软导航

自推出以来,Core Web Vitals 计划一直致力于衡量网站的实际用户体验,而不是网站创建或加载背后的技术细节。这三个 Core Web Vitals 指标是作为以用户为中心的指标创建的,是对现有技术指标(例如 DOMContentLoadedload)的改进,后者衡量的时间往往与用户对网页性能的感知无关。因此,只要网站的表现良好,用于构建网站的技术不应影响评分。

现实情况总是比理想情况要复杂一些,而且核心网页指标从未完全支持广受欢迎的单页应用架构。这些 Web 应用不会在用户浏览网站时加载单独的网页,而是使用所谓的“软导航”,在这种导航中,网页内容由 JavaScript 更改。在这些应用中,通过更改网址并将之前的网址推送到浏览器历史记录中,从而使返回和前进按钮按用户预期运行,从而营造出传统网页架构的错觉。

许多 JavaScript 框架都使用这种模型,但各自的实现方式有所不同。由于这超出了浏览器传统意义上所理解的“网页”的范畴,因此衡量这一点一直很困难:在当前网页上的互动与将其视为网页之间,该如何划分界限?

Chrome 团队已经考虑这个问题一段时间了,并希望对“软导航”的定义进行标准化,以及如何衡量这方面的核心网页指标,就像衡量采用传统多页面架构 (MPA) 的网站一样。虽然仍处于早期阶段,但该团队现已准备好让已实施的功能更广泛地供网站进行实验。这样,网站就可以就目前的方法提供反馈。

什么是软导航栏?

我们对软导航做出了以下定义:

  • 导航由用户操作发起。
  • 此导航会导致网址对用户可见,并且会更改历史记录。
  • 导航会导致 DOM 更改。

对于某些网站,这些启发词语可能会导致假正例(用户实际上不会认为发生了“导航”)或假负例(用户认为发生了“导航”,但实际上不符合这些条件)。欢迎您在软导航规范代码库中针对这些启发词语提供反馈。

Chrome 如何实现软导航栏?

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

这些更改将允许按网页浏览衡量核心网页指标和一些相关的诊断指标,但需要考虑一些细微之处。

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

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

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

如需详细了解如何衡量软导航的指标,请参阅“衡量每次软导航的 Core Web Vitals”部分

如何在 Chrome 中启用软导航栏?

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

对于开发者,可以通过在 chrome://flags/#enable-experimental-web-platform-features 中开启实验性 Web 平台功能标志,或在启动 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)。

衡量每次软导航的 Core Web Vitals

如需添加软导航指标条目,您需要在性能观察器的 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 标志。在性能观察器级别明确选择启用此功能是为了确保现有性能观察器不会对这些额外的条目感到意外,因为在尝试衡量软导航的 Core Web Vitals 时,需要考虑一些额外的注意事项。

系统仍会根据原始的“硬性”导航开始时间返回时间。例如,若要计算软导航栏的 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。但这不是当前实验的一部分。

如何同时衡量新旧版本?

在此实验期间,建议您继续按照当前方式(基于“硬”网页导航)衡量 Core Web Vitals,以便与 CrUX 衡量和报告的内容保持一致,使其成为 Core Web Vitals 计划的官方数据集。

除了这些之外,您还应衡量软导航,以便了解未来如何衡量这些导航,并让您有机会向 Chrome 团队提供有关此实现在实践中运作方式的反馈。这有助于您和 Chrome 团队进一步完善该 API。

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

使用 web-vitals 库衡量软导航的 Core 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 下一个 largest contentful paint 的时间(相对于软导航的开始时间)。系统不会考虑上次导航中存在的现有绘制。因此,LCP 将大于或等于 0。通常,系统会在发生互动或页面进入后台时报告此值,因为只有在那时才能最终确定 LCP。
CLS 导航时间之间最长的时间差。通常,这发生在网页进入后台时,因为只有这样才能最终确定 CLS。如果没有发生偏移,则报告值为 0。
INP 导航时间之间的 INP。通常,系统会在发生互动时或页面进入后台时报告此值,因为只有在那时才能最终确定 INP。如果没有互动,则不会报告 0 值。

这些更改是否会纳入 Core Web Vitals 衡量范围?

这项软导航实验就是一项实验。我们希望先评估这些启发词语,看看它们能否更准确地反映用户体验,然后再决定是否将其纳入 Core Web Vitals 计划。我们非常期待开展这项实验,但无法保证这项实验是否会取代当前的衡量方法,也无法保证何时会取代。

我们非常重视 Web 开发者对实验、所用启发词语以及您认为这些启发词语能否更准确地反映体验的反馈。软导航 GitHub 代码库是提供此类反馈的最佳位置,不过,如果 Chrome 的实现存在个别 bug,则应在 Chrome 问题跟踪器中提出。

CrUX 中如何报告软导航?

如果此实验取得成功,CrUX 中将如何精确报告软导航功能,目前仍未确定。这并不一定意味着它们会像当前的“硬”导航一样被处理。

在某些网页中,对于用户而言,软导航与整个网页加载几乎没有区别,而使用单页应用技术只是实现细节。在某些情况下,它们可能更像是部分加载的额外内容。

因此,我们可能会决定在 CrUX 中单独报告这些软导航,或者在计算给定网页或网页组的 Core Web Vitals 时对其进行加权。随着启发词语的不断发展,我们或许还能完全排除部分加载软导航。

该团队目前正专注于启发词语和技术实现,以便我们判断此实验的成效,因此尚未就这些方面做出任何决定。

反馈

我们正在积极征求有关此实验的反馈,欢迎您通过以下方式提供反馈:

更新日志

由于此 API 处于实验阶段,因此会发生许多更改,比稳定版 API 的更改更多。如需了解详情,请参阅软导航启发词语变更日志

总结

软导航实验是一种令人兴奋的方法,可帮助我们了解 Core Web Vitals 计划如何演变,以衡量我们指标中缺少的现代网络上的常见模式。虽然这项实验才刚刚起步,我们还有许多工作要做,但将目前取得的进展提供给更广泛的 Web 社区进行实验,是迈向成功的重要一步。收集此次实验的反馈是实验的另一个关键环节,因此我们强烈建议对此开发感兴趣的用户利用此次机会帮助完善该 API,确保其能够代表我们希望通过该 API 衡量的内容。

致谢

缩略图图片:Unsplash 用户 Jordan Madrid