发布时间:2023 年 2 月 1 日;上次更新时间:2025 年 7 月 22 日
自推出以来,核心网页指标计划一直致力于衡量网站的实际用户体验,而不是网站的创建或加载方式背后的技术细节。这三项核心 Web 指标是以用户为中心的指标,是对现有技术指标(例如 DOMContentLoaded
或 load
)的改进,这些技术指标衡量的时间往往与用户感知到的网页性能无关。因此,只要网站表现良好,用于构建网站的技术就不应影响得分。
现实情况总是比理想情况复杂一些,而热门的单页应用架构从未获得核心网页指标的完全支持。当用户在网站中浏览时,这些 Web 应用不会加载不同的单独网页,而是使用所谓的“软导航”,即通过 JavaScript 更改网页内容。在这些应用中,通过更改网址并将之前的网址推送到浏览器的历史记录中,可以保持传统网页架构的假象,从而让后退和前进按钮按用户预期的方式工作。
许多 JavaScript 框架都使用此模型,但每种框架的使用方式各不相同。由于这超出了浏览器传统上理解的“网页”范围,因此一直难以衡量:如何界定当前网页上的互动与新网页之间的界限?
Chrome 团队已经考虑这一挑战有一段时间了,目前正寻求标准化“软导航”的定义,并以类似于衡量采用传统多页架构 (MPA) 实现的网站的方式,衡量软导航的核心网页指标。
自上次源试用以来,我们一直在努力改进该 API,现在我们希望开发者在正式发布之前试用最新迭代版本,并就该方法提供反馈。
什么是软导航?
我们提出了以下关于软导航的定义:
- 导航由用户操作发起。
- 导航会导致用户看到的网址发生变化,并导致历史记录发生变化。
- 导航会导致 DOM 发生变化。
对于某些网站,这些启发式方法可能会导致出现假正例(用户实际上不会认为发生了“导航”)或假负例(用户认为发生了“导航”,但实际上不符合这些条件)。欢迎您在软导航规范代码库中就启发法提供反馈。
Chrome 如何实现软导航?
启用软导航启发式方法后(下一部分会详细介绍),Chrome 将更改报告某些性能指标的方式:
- 每次检测到软导航后,系统都会发出
soft-navigation
PerformanceTiming
事件。 - 在导致有意义的绘制的互动之后,系统会发出新的
interaction-contentful-paint
。当此类渲染跨越软导航时,可用于衡量软导航的 Largest Contentful Paint (LCP)。请注意,此重置的原始实现会重置largest-contentful-paint
指标,使其能够重新发出,但我们已确定采用这种替代方法,以便简化操作并扩大未来的适用范围。 - 系统会为每个与事件相关的导航条目添加
navigationId
属性,以对应于性能时间(first-paint
、first-contentful-paint
、largest-contentful-paint
、interaction-contentful-paint
、first-input-delay
、event
和layout-shift
),从而能够计算 Largest Contentful Paint (LCP)、Cumulative Layout Shift (CLS) 和 Interaction to Next Paint (INP) 并将其归因于正确的网址。
这些更改将允许按每次网页导航来衡量核心网页指标和一些相关的诊断指标,不过有一些细微差别需要考虑。
在 Chrome 中启用软导航会带来哪些影响?
启用此功能后,网站所有者需要考虑以下一些变更:
- CLS 和 INP 指标可以按软导航网址进行细分,而不是在整个网页生命周期内进行衡量。
largest-contentul-paint
条目在互动时已最终确定,因此仅用于衡量初始“硬”导航 LCP,无需额外逻辑来更改衡量方式。- 新的
interaction-contentful-paint
指标将从互动中发出,可用于衡量软导航的 LCP。 - 为了将软导航归因于正确的网址,您可能需要在应用代码中使用性能条目时考虑这些条目中的新
navigationID
属性。 - 并非所有用户都支持此软导航 API,尤其是对于旧版 Chrome 和使用其他浏览器的用户。请注意,即使某些用户报告了核心网页指标,他们也可能不会报告软导航指标。
- 作为一项默认未启用的实验性新功能,网站应测试此功能,以防出现意外的副作用。
请咨询您的 RUM 提供商,了解他们是否支持通过软导航来衡量核心网页指标。许多人正计划测试这项新标准,并将之前的注意事项纳入考虑范围。与此同时,部分提供商还允许根据自己的启发式方法对效果指标进行有限的衡量。
如需详细了解如何衡量软导航的指标,请参阅按软导航衡量核心网页指标部分。
如何在 Chrome 中启用软导航?
Chrome 中默认未启用软导航,但您可以通过明确启用此功能来试用软导航。
对于开发者,可以通过在 chrome://flags/#soft-navigation-heuristics
中启用实验性 Web 平台功能标志,或在启动 Chrome 时使用 --enable-features=SoftNavigationHeuristics:mode/advanced_paint_attribution
命令行实参来启用此功能。
如果网站希望为所有访问者启用此功能以了解其影响,则可以从 Chrome 139 开始运行来源测试,只需注册该测试并在 HTML 或 HTTP 标头中添加包含来源测试令牌的元元素即可启用此功能。如需了解详情,请参阅开始使用源试用一文。
网站所有者可以选择在网页上为所有用户或仅为部分用户启用源试用。请务必了解上述影响部分,以便了解此更改可能会如何影响指标的报告方式,尤其是在为很大一部分用户启用此来源试用时。请注意,无论此软导航设置如何,CrUX 都会继续以现有方式报告指标,因此不会受到这些影响。另请注意,源试用还限制为在最多 0.5% 的 Chrome 网页加载中启用实验性功能(以 14 天内的中位数为准),但只有非常大的网站才会遇到此问题。
如何衡量软导航?
启用软导航实验后,系统将使用 PerformanceObserver
API 报告指标,与其他指标一样。不过,对于这些指标,还需要考虑一些额外因素。
报告软导航
您可以使用 PerformanceObserver
来观察软导航。以下是一个代码段示例,用于将软导航条目记录到控制台,包括使用 buffered
选项记录此页面上之前的软导航:
const observer = new PerformanceObserver(console.log);
observer.observe({ type: "soft-navigation", buffered: true });
可用于最终确定上一次导航的完整生命周期页面指标。
针对相应网址报告指标
由于软导航只有在发生后才能看到,因此某些指标需要在发生此事件后最终确定,然后针对之前的网址进行报告,因为当前网址现在会反映新网页的更新网址。
可以使用相应 PerformanceEntry
的 navigationId
属性将事件与正确的网址相关联。您可以使用 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});
随着 API 的最新更改,不再需要 includeSoftNavigationObservations
标志,并且该标志可能会在未来移除,但目前,除了在 Chrome 中启用软导航功能之外,还需要在性能观察器级别明确选择启用。
系统仍会返回相对于原始“硬”导航开始时间的时间。因此,若要计算软导航的 LCP,您需要获取 interaction-contentful-paint
时间,然后减去相应的软导航开始时间(如前文所述),以获得相对于软导航的时间。例如,对于 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: 'interaction-contentful-paint', buffered: true, includeSoftNavigationObservations: true});
有些指标一直以来都是在整个网页生命周期内进行衡量的:例如,LCP 在发生互动之前可能会发生变化。CLS 和 INP 可以更新,直到用户离开相应网页。因此,每次发生新的软导航时,每个“导航”(包括原始导航)可能都需要最终确定上一个网页的指标。这意味着,初始的“硬”导航指标可能会比平时更早确定。
同样,当开始衡量这些长期存在的指标的新软导航的指标时,需要“重置”或“重新初始化”指标,并将其视为新指标,而不会记住之前“网页”设置的值。
对于在导航之间保持不变的内容,应如何处理?
软导航的 LCP(根据 interaction-contentful-paint
计算)将仅衡量新的绘制。这可能会导致 LCP 不同,例如从该软导航的冷加载到软加载。
例如,假设某个网页包含一个作为 LCP 元素的大横幅图片,但其下方的文字会随着每次软导航而变化。初始网页加载会将横幅图片标记为 LCP 元素,并以此为依据计算 LCP 时间。对于后续的软导航,下面的文字将是软导航后绘制的最大元素,并将成为新的 LCP 元素。不过,如果通过深层链接将新网页加载到软导航网址中,横幅图片将成为新的绘制对象,因此可以被视为 LCP 元素。
如本例所示,软导航的 LCP 元素可能会因网页加载方式而异,就像加载带有锚链接的网页(锚链接位于网页下方)可能会导致不同的 LCP 元素一样。
如何衡量 TTFB?
对于常规网页加载,第一字节时间 (TTFB) 表示返回原始请求的第一个字节所用的时间。
对于软导航,这是一个比较棘手的问题。我们是否应衡量针对新网页发出的第一个请求?如果应用中已包含所有内容,并且没有其他请求,会发生什么情况?如果通过预提取提前发出该请求,会怎么样?如果用户发出的请求与软导航无关(例如,是分析请求),会发生什么情况?
一种更简单的方法是,对于软导航,报告的 TTFB 为 0,这与我们建议的往返缓存恢复类似。这是 web-vitals
库用于软导航的方法。
未来,我们可能会支持更精确的方式来了解哪个请求是软导航的“导航请求”,从而能够更精确地测量 TTFB。但这不是当前实现的一部分。
如何同时衡量旧版和新版?
在此实验期间,建议您继续以当前方式衡量核心网页指标,即基于“硬”网页导航,以便与 CrUX 将作为核心网页指标计划的官方数据集来衡量和报告的内容保持一致。
除了这些指标之外,还应衡量软导航,以便您了解未来如何衡量这些指标,并有机会向 Chrome 团队提供有关此实现方式在实践中的效果的反馈。这将有助于您和 Chrome 团队在未来完善 API。
对于 LCP,这意味着旧方式只考虑 largest-contentful-paint
条目,而新方式同时考虑 largest-contentful-paint
和 interaction-contentful-paint
条目。
对于 CLS 和 INP,这意味着像旧方法一样在整个网页生命周期内衡量这些指标,并按软导航分别对时间轴进行切分,以衡量新的单独 CLS 和 INP 值。
使用 web-vitals
库衡量软导航的核心网页指标
考虑所有细微差别的最简单方法是使用 web-vitals
JavaScript 库,该库在单独的 soft-navs branch
中实验性地支持软导航(也可在 npm 和 unpkg 上使用)。您可以通过以下方式衡量此指标(根据需要替换 doTraditionalProcessing
和 doSoftNavProcessing
):
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 值。 |
这些更改是否会纳入核心 Web 指标的衡量范围?
此软导航实验正是一项实验。我们希望先评估这些启发式方法,看看它们是否能更准确地反映用户体验,然后再决定是否将它们纳入核心网页指标计划。我们对这项实验的可能性感到非常兴奋,但无法保证它是否会取代当前的衡量方式,也无法保证取代的时间。
我们非常重视 Web 开发者对实验、所用启发式方法以及您是否认为该实验能更准确地反映体验的反馈。软导航 GitHub 代码库是提供此类反馈的最佳场所,不过 Chrome 在实现该功能时出现的个别 bug 应在 Chrome 问题跟踪器中提出。
CrUX 中将如何报告软导航?
如果此实验成功,CrUX 将如何报告软导航也仍有待确定。不一定保证它们会获得与当前“硬”导航相同的处理方式。
在某些网页中,就用户而言,软导航几乎与整个网页加载完全相同,而单页应用技术的使用只是一个实现细节。而在其他应用中,它们可能更像是部分加载的附加内容。
因此,我们可能会决定在 CrUX 中单独报告这些软导航,或者在计算给定网页或一组网页的核心网页指标时,对这些软导航进行加权。随着启发法的不断发展,我们或许还能完全排除部分加载软导航。
该团队目前正专注于启发式和技术实现,以便我们判断此实验是否成功,因此尚未就这些方面做出任何决定。
反馈
我们正在积极征求有关此实验的反馈意见,您可以通过以下方式提供反馈:
- 软导航启发法和标准化。
- Chrome 实现问题。
- 如需提供有关网页指标的一般反馈,请发送电子邮件至 web-vitals-feedback@googlegroups.com。
更新日志
由于此 API 处于实验阶段,因此与稳定版 API 相比,它会发生更多变更。如需了解详情,请参阅软导航启发式更改日志。
总结
软导航实验是一种令人兴奋的方法,可用于了解核心网页指标计划如何发展,以衡量我们的指标中缺失的现代网络上的常见模式。虽然此实验尚处于初期阶段,还有许多工作要做,但将目前取得的进展提供给更广泛的网络社区进行实验是一项重要举措。收集此次实验的反馈是实验的另一个关键环节,因此我们强烈建议对此开发感兴趣的人员利用此机会帮助塑造 API,确保它能够代表我们希望通过此 API 衡量的指标。
致谢
缩略图图片由 Unsplash 用户 Jordan Madrid 提供
这项工作是 Yoav Weiss 在 Google 时首次开展的工作的延续。感谢 Yoav 在此 API 上付出的努力。