☰
web-vitals 版本演进全解析:从 v0.1 到 v6.2 的核心能力变迁与升级指南
2026/9/25 3:24:53 网站建设 项目流程
  • 前端
  • 可观测性

【免费下载链接】web-vitals

Essential metrics for a healthy site.

项目地址:https://gitcode.com/gh_mirrors/we/web-vitals
点击查看免费下载

导读

web-vitals是 Google Chrome 团队维护的用于测量真实用户 Web 性能指标(CLS、INP、LCP、FCP、TTFB)的轻量级库。本文以仓库根目录 CHANGELOG.md 为脉络主线,完整梳理该库从 2020 年 v0.1 预发布到 v6.2.2 的全部版本迭代:包括 v3 的 API 重构与 attribution 构建、v4 的 INP 归因深化、v5 移除 FID 并引入 LoAF 归因、v6 的 Soft Navigation 支持等关键里程碑,并结合仓库源码(src 目录)验证各版本变更的底层实现。读完本文,你将掌握 web-vitals 各版本的能力边界、破坏性变更清单、升级路径,以及如何利用 attribution 构建定位性能瓶颈。

一、版本全景:六年演进的主线脉络

web-vitals的版本史可以划分为五个明显阶段,对应五大主题:

阶段版本区间核心主题
诞生期v0.1.0 ~ v2.1.4(2020.04 ~ 2022.01)补齐指标测量能力、CLS 定义对齐、批量上报
API 重构期v3.0.0 ~ v3.5.2(2022.08 ~ 2024.01)getXXX()→onXXX()、配置对象、attribution 构建、INP 引入
归因深化期v4.0.0 ~ v4.2.4(2024.05 ~ 2024.10)INP 分段时间、LoAF 归因、内存泄漏修复
度量体系调整期v5.0.0 ~ v5.3.0(2025.05 ~ 2026.05)移除 FID、Baseline 支持策略、LoAF 扩展归因
软导航时代v6.0.0 ~ v6.2.2(2026.07 ~ 2026.09)Soft Navigation 支持、内存与边界修复

其中 v3.0.0、v4.0.0、v5.0.0、v6.0.0 四个大版本均包含破坏性变更(BREAKING),官方为每个大版本提供了专门的升级指南:见 docs/upgrading-to-v4.md、docs/upgrading-to-v5.md、docs/upgrading-to-v6.md。

二、诞生期(v0.1 ~ v2.x):从预发布到指标定义对齐

2.1 初始发布与早期稳定化

  • v0.1.0(2020-04-24):首次预发布。
  • v0.2.0(2020-05-03):正式公开发布。此前两个补丁(v0.2.1/v0.2.2)确保了所有模块为纯模块(pure modules)、补齐 TypeScript 导出与配置,并移除了 package 的type字段。
  • v0.2.3(2020-06-26):确保仅当 PerformanceObserver 成功创建时才上报——这是早期针对不支持 API 的浏览器的重要防御(该防御逻辑至今仍保留,见 src/lib/observe.ts 中的try/catch与supportedEntryTypes过滤)。
  • v0.2.4(2020-07-23):移除unload事件监听器,为后续推荐visibilitychange/pagehide埋下伏笔。

2.2 v1.0.0:bfcache 上报与接口定型(破坏性变更)

v1.0.0(2020-11-16)做了三项重要变更:

  • [BREAKING]支持在往返缓存(back/forward cache)恢复后上报指标:bfcache 恢复被视为一次独立的页面访问,所有指标会以新的 metric 对象重新上报。
  • [BREAKING]从Metric接口中移除isFinal标志(见 README.md 中的Metric接口定义)。
  • 移除用于停止 LCP 观察的 scroll 监听器。

这一阶段的底层机制在 src/lib/initMetric.ts 中可以看到:navigationType的判定优先使用 bfcache 恢复时间(getBFCacheRestoreTime() >= 0时标记为'back-forward-cache'),其次才依据 Navigation Timing 条目判断prerender、restore等类型。

2.3 v2.x:CLS 定义对齐与批量上报

v2.0.0(2021-06-01)是 CLS 度量方式的分水岭:

  • [BREAKING]将 CLS 更新为最大会话窗口(max session window)5 秒、间隔上限(gap)1 秒的算法(对应 src/onCLS.ts 与 src/lib/LayoutShiftManager.ts 的实现)。
  • 确保仅在页面可见时上报 CLS。
  • 仅在 FCP 已上报时才上报 CLS(对齐官方指标口径)。
  • 更新唯一 ID 的版本前缀。

v2.1.0(2021-07-01)引入批量上报支持:由于各指标并非同时就绪,官方建议维护一个队列、在页面进入后台或卸载时统一 flush,并推荐使用navigator.sendBeacon()。该模式在 README.md 中有完整示例。

v2.1.x 阶段还处理了一系列兼容性问题:为 Opera mini 极限省流模式补充特性检测(v2.1.1)、确保 TTFB 上报值小于当前页面时间(v2.1.2)、LCP 仅在首次隐藏前发生时才上报(v2.1.3)、防止 bfcache 恢复后重复上报 TTFB(v2.1.4)。

三、v3.0.0:API 重构元年

3.1 破坏性变更:函数命名与签名

v3.0.0(2022-08-24)是使用方式变化最大的一次发布:

  • [BREAKING]将getXXX()系列函数全部改名为onXXX()(如getCLS()→onCLS()),语义从"获取当前值"变为"持续监听并上报",与指标可能多次上报的行为一致。
  • [BREAKING]为所有指标函数增加配置对象参数(opts),默认值为{},即onCLS(callback, opts?)的形式。
  • [BREAKING]将ReportHandler类型更名为ReportCallback,并保留别名以向后兼容。
  • [BREAKING]支持 bfcache 恢复后上报 TTFB(v2.1.4 时禁止,v3 改为支持,因为 bfcache 恢复被视为新的页面访问)。
  • [BREAKING]metric 的entries数组只保留最后一个LCP 条目。
  • 更新 metric ID 前缀(v3 专用),并将 Navigation Timing polyfill 移入 base+polyfill 构建。

3.2 新能力:attribution 构建、INP 与 rating

v3.0.0 同时引入了三个影响深远的新特性:

  1. attribution 构建(dist 中的web-vitals.attribution.*系列产物):每个指标回调除Metric外额外携带attribution对象,用于定位真实用户场景下的性能瓶颈根因。包内同时提供 attribution.js / attribution.d.ts 作为入口。
  2. INP(Interaction to Next Paint)指标支持:作为当时的新兴 Core Web Vitals 指标进入库内(见 src/onINP.ts)。
  3. rating属性与MetricRatingThresholds:每个上报的 metric 自带'good' | 'needs-improvement' | 'poor'评级;阈值以[number, number]二元组形式导出(见 src/index.ts 中的CLSThresholds、INPThresholds、LCPThresholds等常量,例如INPThresholds = [200, 500])。

[!NOTE] 从 CHANGELOG 看,v3.2.0 的版本号被跳过("Version number skipped"),因此实际发布序列是 v3.1.x → v3.3.x。

3.3 v3.1 ~ v3.5:稳定性与细节打磨

这一阶段的小版本集中在行为对齐与健壮性:

  • v3.1.0:新增'restore'导航类型(浏览器 discard 后由用户恢复);reportAllChanges时上报初始 CLS 值;所有 observer 延迟到页面激活(activation)后再创建;忽略responseStart为 0 的 TTFB;延迟执行 observer 回调。
  • v3.1.1:CLS 逻辑延迟到onFCP()回调之后执行。
  • v3.3.0:在 attribution 构建中也导出评级阈值;裁剪 classname 选择器;防止隐藏的 prerender 页面上报 LCP;文档补充 Server Timing 信息。
  • v3.3.2:修复 attribution 类型;安全访问 navigation entry 类型。
  • v3.4.0:bindReporter泛型化(见 src/lib/bindReporter.ts,其中getRating()依据阈值二元组判定good/needs-improvement/poor);修复 SVG 元素的选择器生成。
  • v3.5.0:onLCP回调在独立任务中运行;修复durationThreshold设为 0 时的 INP 缺陷;防止不支持 INP 的浏览器把 FID 条目当作 INP 上报。
  • v3.5.2:INP 归因选择第一个非空target。

四、v4.0.0:归因能力深化

4.1 破坏性变更:类型与字段命名规范化

v4.0.0(2024-05-13)的破坏性变更集中在类型系统与归因字段命名:

  • [BREAKING]类型升级为更通用的用法,支持import type显式导入。
  • [BREAKING]拆分waitingDuration,使重定向延迟更易理解(TTFB 归因中,waitingDuration表示从用户发起加载到页面开始处理请求的总时长,重定向会显著拉大该值)。
  • [BREAKING]TTFBAttribution字段从*Time统一更名为*Duration(如cacheDuration、dnsDuration、connectionDuration、requestDuration)。
  • [BREAKING]LCP 归因中resourceLoadTime更名为resourceLoadDuration。
  • [BREAKING]新增 INP 分段时间(breakdown timings)与LoAF(Long Animation Frame)归因。
  • [BREAKING]弃用onFID(),并移除此前已弃用的 API。

4.2 归因对象细化:INP 三段式拆解

v4 之后 INP 归因将一次交互拆解为三段可诊断的时间分量(对应 README.md 中的INPAttribution):

  • inputDelay:用户交互到浏览器开始处理事件监听器之间的延迟(主线程忙碌导致)。
  • processingDuration:首个事件监听器开始运行到全部事件监听器处理完毕的时长。
  • presentationDelay:事件处理结束到下一帧呈现在屏幕上的时长(含主线程的 rAF/ResizeObserver 回调与样式布局计算,以及合成器/GPU/栅格化等主线程外工作)。

从 src/onINP.ts 的实现看,INP 值通过InteractionManager._estimateP98LongestInteraction()取交互延迟的第 98 百分位近似;归因构建对应的 src/attribution/onINP.ts 在此基础之上叠加 LoAF 信息(longAnimationFrameEntries、longestScript、totalScriptDuration、totalStyleAndLayoutDuration等)。

4.3 v4.1 ~ v4.2:修复与健壮性

  • v4.1.0:将支持性检查移到onINP()函数顶部(尽早返回,见 src/onINP.ts 开头对PerformanceEventTiming与interactionId的守卫);修复 LoAF 条目先于 event 条目派发时缺失归因的问题。
  • v4.2.0:重构 INP 归因代码以修复 Windows 10 上的错误。
  • v4.2.1:兼容 TypeScript v5.5。
  • v4.2.2:修复 bfcache 恢复后的交互计数(依赖 src/lib/polyfills/interactionCountPolyfill.ts 的 polyfill 行为)。
  • v4.2.3 / v4.2.4:修复 INP 归因中缺失的 LoAF 条目;修复每次keydown/click都注册新事件监听器导致的内存泄漏。

五、v5.0.0:度量体系调整

5.1 破坏性变更:告别 FID

v5.0.0(2025-05-07)标志着 Core Web Vitals 度量体系的正式切换:

  • [BREAKING]移除已弃用的onFID()函数(FID 指标正式退役,由 INP 全面取代)。
  • [BREAKING]浏览器支持策略切换为Baseline Widely Available:所有代码使用的 JavaScript 特性均属于该基线,从而保证近 30 个月内发布的主流浏览器(Chrome、Firefox、Safari)可直接运行。
  • [BREAKING]对 attribution 选择器中出现的类名进行排序以降低基数(cardinality),减小上报数据的维度爆炸。

5.2 INP 归因扩展:LoAF 深入

v5.0.0 将 INP 归因扩展到 LoAF 的更深层:

  • 新增**最长脚本(longest script)摘要与脚本时长分桶(buckets)**信息:INPLongestScriptSummary包含entry、subpart('input-delay' | 'processing-duration' | 'presentation-delay')与intersectingDuration。
  • 支持在 attribution 构建中通过generateTarget选项自定义 target 生成函数(默认使用 src/lib/getSelector.ts 生成选择器字符串;自定义函数返回null/undefined时回退到默认实现)。
  • 支持以不同配置多次调用onINP()——底层通过 src/lib/initUnique.ts 的WeakMap机制为每个独立配置对象创建唯一的InteractionManager实例,同一配置对象重复调用则复用实例。
  • 使用visibility-state 性能条目(PerformanceVisibilityState类条目)以更准确地在隐藏状态下收尾指标。

5.3 数值边界收敛

v5.0.0 还做了一组"数值钳制(cap)",确保归因分项之和不会超过指标总值:

  • nextPaintTime钳制到processingStart。
  • INP 分段时间合计钳制到 INP 总时长。
  • LCP 资源加载时长钳制到 LCP 总时长。
  • 确保 idle 回调不会执行两次(合并了两个相关 PR)。

5.4 v5.1 ~ v5.3:性能与内存优化

  • v5.1.0:尽早注册visibilitychange监听;LCP 仅在用户事件(isTrusted=true)上最终化(防止误报);自定义getSelector为null/undefined时回退默认实现。
  • v5.2.0:用find()替代filter()[0]提升性能;用queueMicrotask调度微任务(对应 src/lib/observe.ts 中规避 Safari 回调时序问题的实现);简化 event 与 LoAF 条目的清理逻辑;移除过时的 FID polyfill 类型;LCP 元素被移出 DOM 时回退使用LargestContentfulPaint.id;修复延迟加载场景下onLCP的缺陷;处理初始隐藏页面与可见性变化时注册onLCP的场景;确保whenIdleOrHidden清理 idle 回调;限制 pending 事件数量以节省内存;新增includeProcessedEventEntries选项;通过重构进一步缩小打包体积。
  • v5.3.0:移除getFirstHiddenTimePolyfill;修复同一配置对象传给多个指标函数导致报错的问题;为 INP 增加更健壮的interactionTarget设置。

六、v6.0.0:Soft Navigation 时代

6.1 核心新特性:软导航(Soft Navigation)支持

v6.0.0(2026-07-21)的旗舰特性是为支持软导航的浏览器(Chromium 151+)提供 Core Web Vitals 的软导航上报。所谓软导航,是指用户交互 → URL 变化 → 页面有新内容绘制三者同时发生时,浏览器自动识别的一次"导航",使 SPA 无需框架接入即可被统一测量。

软导航在指标语义上有以下差异(详见 README.md):

  • TTFB 在软导航后按 0 上报(而非首个网络请求的时间)。
  • FCP/LCP 只统计软导航之后的首次/最大内容绘制;软导航之间保留未重绘的元素不计数。
  • INP 重置为只统计软导航之后的交互。
  • CLS 与首页分离、重新测量。

启用方式是在配置对象中传{reportSoftNavs: true}。底层实现见 src/lib/softNavs.ts:checkSoftNavsEnabled()同时检查PerformanceObserver.supportedEntryTypes是否包含'soft-navigation'、PerformanceSoftNavigation.prototype.getLargestInteractionContentfulPaint是否为函数(Firefox 存在可禁用该功能的偏好设置,故需守卫),且要求opts.reportSoftNavs为真。

6.2 其他 v6 变更

  • [BREAKING]通过 tsconfig 的verbatimModuleSyntax移除多余的模块导入(类型改为显式import type导入,见 docs/upgrading-to-v6.md)。
  • 新增 source maps(便于线上调试源码)。
  • 将requestIdleCallback钳制为 1 秒,确保即使主线程繁忙指标也能及时上报——对应 src/lib/whenIdleOrHidden.ts 中const timeout = 'requestIdleCallback' in globalThis ? 1000 : 0;的实现,忙碌页面在reportAllChanges下可能因此更频繁上报。
  • 翻转includeProcessedEventEntries默认值为false(v5.2.0 引入时为 true),以减小归因对象体积与内存占用。
  • 为 INP 增加bfcache 恢复后的小交互上报支持(bfcache 恢复时创建新的 metric 对象,见 src/onINP.ts 的onBFCacheRestore分支)。

6.3 v6.1 ~ v6.2:收尾修复

v6.1.x 与 v6.2.x 以内存与边界修复为主,且每一条都可在源码中找到对应实现:

  • v6.1.0:为 LCP attribution 增加Resource Timing 缓冲(对应LCPAttributionReportOpts.resourceBufferSize,默认 50,即在前 250 条默认缓冲之外最多再缓冲 50 条资源条目,用于将媒体类 LCP 归因到 URL)。
  • v6.1.1:将导航交互计数作用域限定到每个 InteractionManager(修复软导航场景下交互计数串号)。
  • v6.2.0:防止 bfcache 恢复后误报 CLS 0 值;为旧浏览器守卫supportedEntryTypes。
  • v6.2.1:修复 INP attribution 中inputDelay为负值的问题。
  • v6.2.2:限制 pending 的 LoAF 数量以防止内存泄漏——这与 src/lib/softNavs.ts 中storeSoftNavEntry只保留最近 2 条软导航条目的设计一脉相承:库内所有"按需暂存"的数据结构都遵循有界原则。

七、升级路径与实操要点

7.1 大版本升级总览

升级目标主要破坏性变更官方指南
v3 → v4类型显式化、TTFB/LCP 归因字段更名、INP 分段时间与 LoAF 归因、onFID()弃用docs/upgrading-to-v4.md
v4 → v5onFID()移除、Baseline Widely Available、attribution 选择器类名排序docs/upgrading-to-v5.md
v5 → v6verbatimModuleSyntax显式类型导入、includeProcessedEventEntries默认值翻转docs/upgrading-to-v6.md

7.2 紧跟版本的配置要点

结合 CHANGELOG 与源码,当前(v6.x)推荐的核心配置如下:

import {onCLS, onINP, onLCP, onTTFB, onFCP} from 'web-vitals'; // 需要诊断根因时改用: // import {onCLS, onINP, onLCP} from 'web-vitals/attribution'; onCLS(console.log, {reportAllChanges: false}); // INP:durationThreshold 默认 40ms(见 src/onINP.ts 的 DEFAULT_DURATION_THRESHOLD) onINP(console.log, { durationThreshold: 40, // v6 起默认 false;仅当确需完整事件列表诊断输入延迟时开启 includeProcessedEventEntries: false, }); onLCP(console.log, { // LCP 归因中额外缓冲的 Resource Timing 条目数,默认 50 resourceBufferSize: 50, }); // 软导航(Chromium 151+): onCLS(console.log, {reportSoftNavs: true}); onINP(console.log, {reportSoftNavs: true}); onLCP(console.log, {reportSoftNavs: true});

7.3 从 CHANGELOG 中提炼的实践红线

回看六年变更记录,可以提炼出几条始终被维护者遵守的工程原则,也是使用本库时的实践红线:

  1. 监听器生命周期必须闭环:v0.2.4 移除 unload 监听、v4.2.4 修复每次按键/点击注册新监听器、v5.0.3 移除不再需要的 visibilitychange 监听器、v5.2.0 清理whenIdleOrHidden的 idle 回调——反复的"注册/清理"修复提示我们:重复调用onXXX()会持续累积监听器与 PerformanceObserver,应避免在同一页面反复注册(README 亦有明确警告)。
  2. 内存有界是硬约束:v5.2.0 限制 pending 事件、v6.2.2 限制 pending LoAF、softNavs 只保留最近 2 条软导航条目——说明归因数据再有用,也不允许无界增长。
  3. 上报时机贴近页面生命周期:指标在visibilitychange到 hidden、页面卸载或 bfcache 恢复等节点收尾上报,配合navigator.sendBeacon()与批量队列使用(见 README.md)。
  4. 归因数值需要边界钳制:v5.0.0 对nextPaintTime、INP breakdown、LCP load duration 的 cap 处理,保证了"分项之和 ≤ 总量",诊断时不会出现归因数据自相矛盾。

八、总结

从 v0.1 的预发布到 v6.2.2,web-vitals的演进路径清晰可循:指标语义对齐(CLS 会话窗口)→ API 重构与归因构建引入(v3)→ INP 与 LoAF 归因深化(v4/v5)→ 软导航测量(v6)。每一个大版本都伴随明确的破坏性变更清单与升级指南,小版本则持续打磨内存边界、监听器生命周期、数值钳制与浏览器兼容守卫。对于使用者而言,理解这条演进主线,既能安全地完成版本升级,也能在阅读 CHANGELOG.md 与 src 源码时快速定位每个行为背后的设计动机。

  • 前端
  • 可观测性

【免费下载链接】web-vitals

Essential metrics for a healthy site.

项目地址:https://gitcode.com/gh_mirrors/we/web-vitals
点击查看免费下载
上一篇:Nixpkgs 实战指南:用 wrapFirefox 与 fetchFirefoxAddon 构建预装扩展、注入企业策略的定制 Firefox
下一篇:darktable 免费入门:RAW 照片从发灰到出片,一篇讲清

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询