衡量实际网页指标的最佳做法

如何使用您当前的分析工具衡量网页指标。

衡量和报告网页的实际性能对于诊断和改进网页性能至关重要。如果没有实测数据,就不可能确定对网站所做的更改是否真正实现了预期效果。

许多热门的实时用户监控 (RUM) 分析服务提供商已经在他们的工具中支持核心网页指标指标(以及许多其他网页指标)。如果您目前正在使用其中一种 RUM 分析工具,则可以很好地评估您网站上的网页在多大程度上满足建议的核心网页指标阈值,并防止日后出现回归问题。

虽然我们建议您使用支持 Core Web Vitals 指标的分析工具,但如果您当前使用的分析工具不支持这些指标,则无需切换。几乎所有分析工具都提供了一种定义和衡量自定义指标事件的方法,这意味着您可以使用当前的分析工具来衡量核心网页指标指标,并将其添加到现有的分析报告和信息中心。

本指南介绍了使用第三方或内部分析工具衡量核心网页指标(或任何自定义指标)的最佳实践。对于希望为其服务添加 Core Web Vitals 支持的分析服务供应商,本框架也可作为指导。

使用自定义指标或事件

如上所述,大多数分析工具都可以让您衡量自定义数据。如果您的分析工具支持此功能,您应该能够使用此机制衡量每个 Core Web Vitals 指标。

在分析工具中衡量自定义指标或事件通常分为三个步骤:

  1. 在工具的管理员中定义或注册自定义指标(如果需要)。(注意:并非所有分析服务提供商都需要提前定义自定义指标。)
  2. 计算前端 JavaScript 代码中的指标值。
  3. 将指标值发送到您的分析后端,确保名称或 ID 与第 1 步中定义的名称或 ID 一致(再次根据需要)

对于第 1 步和第 3 步,您可以参阅分析工具的文档来了解说明。在第 2 步中,您可以使用 web-vitals JavaScript 库计算每个 Core Web Vitals 指标的值。

以下代码示例展示了用代码跟踪这些指标并将其发送到分析服务有多么容易。

import {onCLS, onINP, onLCP} from 'web-vitals';

function sendToAnalytics({name, value, id}) {
  const body = JSON.stringify({name, value, id});
  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
      fetch('/analytics', {body, method: 'POST', keepalive: true});
}

onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);

避免计算平均值

人们往往倾向于通过计算平均值来对性能指标的一系列值求和。乍一看,平均值似乎很方便,因为它们只是对大量数据的简明摘要,但您应该避免依靠它们来解读网页性能的冲动。

平均值存在问题,因为它们不代表任何单个用户的会话。分布的任何一个范围内的离群值都可能以误导性方式使平均值出现偏差。

例如,一小部分用户可能使用速度极慢的网络或设备,这些网络或设备即将达到值的最大范围,但没有考虑到足够的用户会话,以致于无法暗示存在问题的平均值。

请尽可能使用百分位数,而不是平均值。给定性能指标在分布中的百分位数能更好地描述网站的整体用户体验。这样,您就可以专注于一部分实际体验,从而获得比单一价值更高的数据洞见。

确保您可以报告分布情况

计算每个 Core Web Vitals 指标的值并使用自定义指标或事件将这些值发送到您的分析服务后,下一步是构建报告或信息中心来显示收集的值。

为确保您达到建议的核心网页指标阈值,您需要在报告中的第 75 个百分位显示每个指标的值。

如果您的分析工具不提供分位数报告作为内置功能,您可能仍然可以手动获取此数据,方法是生成一个报告,列出按升序排序的每个指标值。此报告生成后,在经过排序的完整报告中所有值列表的 75% 处的结果即为该指标的第 75 个百分位,无论您如何细分数据(按设备类型、连接类型、国家/地区等),此结果都是如此。

如果您的分析工具默认不提供指标级别的报告粒度,如果您的分析工具支持自定义维度,您或许可以实现相同的结果。通过为您跟踪的每个指标实例设置唯一的自定义维度值,如果您在报告配置中包含自定义维度,应该能够生成按各个指标实例细分的报告。由于每个实例都有唯一的维度值,因此不会分组。

“网页指标”报告就是使用 Google Analytics(分析)的分析法的一个示例。该报告的代码是开源,因此开发者可以参考本版块中概述的技术示例。

网页指标报告的屏幕截图

在恰当的时机发送您的数据

一些性能指标可以在网页加载完成后计算,而其他性能指标(如 CLS)则考虑网页的整个生命周期,并且仅在网页开始卸载后才最终确定。

但是,这可能会带来问题,因为 beforeunloadunload 事件都不可靠(尤其是在移动设备上),并且不建议使用这两个事件(因为它们可能会妨碍网页被往返缓存)。

对于跟踪网页整个生命周期的指标,最好在网页的可见性状态变为 hidden 时,在 visibilitychange 事件期间发送指标的当前值。这是因为,一旦网页的可见性状态更改为 hidden,就无法保证该网页上的任何脚本都能再次运行。在移动操作系统中尤其如此,在此类操作系统中,浏览器应用本身可以关闭,而不触发任何页面回调。

请注意,在切换标签页、切换应用或关闭浏览器应用本身时,移动操作系统通常会触发 visibilitychange 事件。它们还会在关闭标签页或导航到新页面时触发 visibilitychange 事件。这使得 visibilitychange 事件比 unloadbeforeunload 事件更可靠。

长期监控性能

当您更新了 Google Analytics(分析)实现,以跟踪和报告 Core Web Vitals 指标后,下一步就是跟踪网站更改在一段时间内对性能有何影响。

对更改进行版本控制

跟踪更改的一种普通(但最终不可靠)方法是将更改部署到生产环境中,然后假定在部署日期之后收到的所有指标对应于新网站,并且在部署日期之前收到的所有指标对应于旧网站。但是,任何因素(包括 HTTP、Service Worker 或 CDN 层的缓存)都可能会阻止其工作。

更好的方法是为部署的每个更改创建唯一的版本,然后在分析工具中跟踪该版本。大多数分析工具都支持设置版本。如果您的自定义维度不存在,您可以创建一个自定义维度,并将该维度设置为您部署的版本。

运行实验

通过同时跟踪多个版本(或实验),您可以更进一步地进行版本控制。

如果分析工具支持定义实验组,请使用该功能。 或者,您也可以使用自定义维度来确保每个指标值都可以与报告中的特定实验组相关联。

在分析中实施实验后,您可以向一部分用户发布实验性更改,并将该更改的效果与对照组用户的效果进行比较。确信某项更改确实能提升性能后,您就可以向所有用户发布该更改。

确保衡量结果不会影响效果

在衡量真实用户的性能时,请务必确保您运行的任何性能衡量代码都不会对网页性能产生负面影响。如果确实如此,那么您试图根据效果对业务的影响而得出的任何结论都是不可靠的,因为您永远无法知道存在分析代码本身是否会造成最大的负面影响。

在生产网站上部署 RUM 分析代码时,请始终遵循以下原则:

推迟分析

Google Analytics(分析)代码应始终以异步、非阻塞的方式加载,通常应最后加载。如果您以阻塞方式加载分析代码,可能会对 LCP 产生负面影响。

所有用于衡量 Core Web Vitals 指标的 API 都是专为支持异步和延迟脚本加载(通过 buffered 标志)而设计的,因此您无需急于提前加载脚本。

如果您要衡量的指标在网页加载时间轴的后期无法计算,则应该仅将需要提前运行到文档的 <head> 中的代码(因此它不是阻塞渲染的请求)并推迟其余代码。不要仅仅因为单个指标需要就提前加载所有分析数据。

请勿创建耗时较长的任务

分析代码通常会为了响应用户输入而运行,但如果您的分析代码正在执行大量 DOM 测量或使用其他处理器密集型 API,则分析代码本身可能会导致输入响应速度很差。此外,如果包含分析代码的 JavaScript 文件很大,执行该文件可能会阻塞主线程,并对网页的 Interaction to Next Paint (INP) 产生负面影响。

使用非阻塞 API

sendBeacon()requestIdleCallback() 等 API 经过专门设计,能以不会阻塞用户关键任务的方式运行非关键任务。

这些 API 非常适合用于 RUM 分析库。

一般来说,所有分析信标都应使用 sendBeacon() API(如果有)发送,所有被动分析衡量代码都应在空闲期间运行。

不要跟踪超出您需要的内容

浏览器会显示大量性能数据,但数据可用并不一定意味着您应该记录这些数据并将其发送到您的分析服务器。

例如,Resource Timing API 提供了网页上加载的每项资源的详细计时数据。但是,所有这些数据不一定或有助于提升资源加载性能。

简而言之,不要仅仅因为数据就跟踪数据而去跟踪数据,还要确保在使用资源进行跟踪之前使用数据。