Chrome 151 的 Soft Navigations API 终于让单页应用 (SPA) 能够针对应用内的每一次导航报告 Core Web Vitals,但 Google 的 CrUX 数据集仍然仅记录首次硬加载 (hard load),这使得开发者面临两种截然不同的性能视图。

为什么 SPA 指标一直滞后

Core Web Vitals——包括 Largest Contentful Paint (LCP)、Interaction-to-Next-Paint (INP) 和 Cumulative Layout Shift (CLS)——是围绕硬导航 (hard navigations) 定义的。硬导航会获取一个全新的文档并丢弃前一个页面的状态。

使用 React、Vue、Next.js 或类似框架构建的 SPA 很少触发硬导航。点击链接会通过 History API 更新 URL,在后台获取数据,并在不进行完整刷新的情况下更换内容。现有的 Performance API 只能捕获初始页面加载,因此 LCP 和 INP 无法感知用户在不同路由之间切换时所感受到的延迟。

这种盲点扭曲了从 Performance Timeline 或 Google 的 Chrome User Experience Report (CrUX) 获取数据的仪表板。它们通常会显示“外壳”页面 (shell page) 极佳的 LCP,却忽略了应用深层加载较慢的情况,从而产生性能良好的错觉。

Chrome 的 Soft Navigations API

Chrome 151 引入了 Soft Navigations API,这是一套将某些 SPA 交互视为真实导航的启发式规则。该 API 监控三个信号:

  • 用户发起的交互(点击、轻触、键盘事件)
  • 通过 History API 进行的 URL 变更
  • 渲染新内容的后续绘制 (paint) 事件

当这三个条件同时满足时,Chrome 会在 Performance Timeline 中记录一次软导航 (soft navigation),并像对待硬导航一样,为该转换计算 Core Web Vitals。开源的 web-vitals 库已于 7 月 21 日增加了支持,因此开发者可以使用现有的 API 开始获取这些数据。

在实践中,你现在可以看到每次路由变更的 LCP 值、反映最后一次用户输入真实延迟的 INP,以及捕获软导航后布局偏移的 CLS。

数据分歧:Chrome vs. CrUX

Google 的 CrUX (Chrome User Experience Report) 为 PageSpeed Insights、Search Console 以及间接的排名信号提供支持。CrUX 目前仍然仅聚合硬导航数据。

因此,你会得到两组一致但不同的数据流:

  • 内部工具:读取 Performance Timeline 的工具现在可以显示路由级别的 LCP、INP 和 CLS,从而真实地反映 SPA 用户的体验。
  • Google 的公开数据集:继续仅显示首次页面加载的指标,这也是 Search Console 报告的内容以及 Google 排名算法所引用的内容。

两者都是正确的;它们只是测量了不同的时刻。仅依赖 Search Console 可能会掩盖初始加载后发生的性能退化,而仅依靠内部仪表板则无法反映 Google 用于 SEO 的基准。

开发者需要关注的事项

  • 浏览器支持 – 目前 Soft Navigations API 仅存在于基于 Chromium 的浏览器中。Safari 和 Firefox 尚缺乏同类功能,因此你必须为部分用户保留回退逻辑 (fallback logic)。
  • 启发式限制 – API 根据一组线索来判定软导航。如果你的应用在不改变 URL 的情况下更新内容(例如模态框叠加或无限滚动),API 可能会错过这些转换,导致数据出现缺口。
  • 先测试后信任 – 由于检测是基于启发式规则的,请在你的应用上运行一系列真实世界的交互,并将报告的指标与手动计时(例如使用 performance.mark)进行对比。只有在确认准确性之后,才应根据这些新数据做出优化决策。

总结

Chrome 151 为 SPA 开发者提供了期待已久的能力,可以测量每次应用内路由变更的 LCP、INP 和 CLS,但 Google 的排名数据仍然仅反映首次硬加载。在 CrUX 跟进之前,团队必须同时处理两套并行的数据集:一套讲述真实的用户的体验,另一套驱动搜索排名。在竞争激烈的 Web 生态系统中,平衡两者并为更广泛的浏览器支持做好准备,将是保持“性能优先”型 SPA 的关键。