尝试衡量软导航

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

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

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

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

什么是软导航栏?

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

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

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

Chrome 如何实现软导航栏?

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

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

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

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

  • 系统可能会针对软导航重新发出其他 FP、FCP 和 LCP 事件。Chrome 用户体验报告 (CrUX) 会忽略这些额外的值,但这可能会影响您网站上的任何真实用户衡量 (RUM) 监控。如果您有任何疑虑,请咨询 RUM 提供商,了解这是否会影响这些衡量结果。请参阅“衡量软导航的 Core Web Vitals”部分
  • 在使用这些条目的应用代码中,您可能需要考虑性能条目上的新(可选)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。但这不是当前实验的一部分。

如何同时衡量新旧版本?

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

除了这些之外,您还应衡量软导航,以便了解未来如何衡量这些导航,并让您有机会向 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 计划。我们非常高兴能够进行这项实验,但无法保证这项实验是否会取代当前的测量结果或何时。

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

CrUX 中如何报告软导航?

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

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

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

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

反馈

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

更新日志

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

总结

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

致谢

缩略图图片:Unsplash 用户 Jordan Madrid