往返缓存 notRestoredReasons API

查找哪些导航被禁止使用 bfcache,以及原因。

添加到 PerformanceNavigationTiming 类中的 notRestoredReasons 属性会报告文档中是否存在的帧在导航时被阻止使用 bfcache,以及原因。开发者可以使用这些信息来确定哪些网页需要更新以使其与 bfcache 兼容,从而提升网站性能。

当前状态

notRestoredReasons API 已从 Chrome 123 开始提供,并正在逐步推出。

概念和用法

新式浏览器为历史记录导航提供了一项名为往返缓存 (bfcache) 的优化功能。这样,当用户返回到之前访问过的网页时,即可获得即时加载体验。网页可能会因各种原因而被阻止进入 bfcache,或者在 bfcache 中被驱逐,其中一些原因是规范要求的,一些原因则特定于浏览器实现。

以前,虽然有 Chrome 开发者工具中的测试,但开发者无法了解其网页在现场被禁止使用 bfcache 的原因。为了在现场启用监控功能,我们扩展了 PerformanceNavigationTiming 类,使其包含 notRestoredReasons 属性。这会返回一个对象,其中包含有关顶部框架和文档中所有 iframe 的相关信息:

  • 被禁止使用 bfcache 的原因。
  • 框架 idname 等详细信息,有助于识别 HTML 中的 iframe。

    这样,开发者就可以采取措施使这些网页与 bfcache 兼容,从而提升网站性能。

示例

PerformanceNavigationTiming 实例可以从 Performance.getEntriesByType()PerformanceObserver 等功能中获取。

例如,您可以调用以下函数来返回效果时间轴中存在的所有 PerformanceNavigationTiming 对象,并记录其 notRestoredReasons

function returnNRR() {
  const navEntries = performance.getEntriesByType("navigation");
  for (let i = 0; i < navEntries.length; i++) {
    console.log(`Navigation entry ${i}`);
    let navEntry = navEntries[i];
    console.log(navEntry.notRestoredReasons);
  }
}

对于历史记录导航,PerformanceNavigationTiming.notRestoredReasons 属性会返回一个采用以下结构的对象,该结构表示顶级帧的屏蔽状态:

{
  children: [],
  id: null,
  name: null,
  reasons: [
    {"reason", "unload-listener"}
  ],
  src: null,
  url: "https://www.example.com/page/"
}

这些属性如下所示:

children
一个对象数组,表示嵌入在顶级帧中的任何同源帧的屏蔽状态。每个对象的结构与父对象相同,这样,对象中可以递归地表示任意数量的嵌套帧级别。如果帧没有子项,则数组将为空。
id
一个字符串,表示帧的 id 属性值(例如 <iframe id="foo" src="...">)。如果帧没有 id,则值为 null。对于顶级页面,此值为 null
name
一个字符串,表示帧的 name 属性值(例如 <iframe name="bar" src="...">)。如果帧没有 name,则值为空字符串。对于顶级页面,此值为 null
reasons
一个字符串数组,其中每个字符串代表导航到的网页被禁止使用 bfcache 的原因。导致屏蔽的原因有很多。如需了解详情,请参阅屏蔽原因部分。
src
一个字符串,表示帧来源的路径(例如 <iframe src="b.html">)。如果帧没有 src,则值为空字符串。对于顶级页面,此值为 null
url
表示导航到的网页/iframe 的网址的字符串。

对于不代表历史记录导航的 PerformanceNavigationTiming 对象,notRestoredReasons 属性将返回 null

请注意,当没有阻塞原因时,notRestoredReasons 也会返回 null,因此 null 并不表示是否使用了 bfcache。为此,您必须使用 event.persisted 属性

报告同源帧中的 bfcache 阻塞

如果网页嵌入了同源框架,则返回的 notRestoredReasons 值将在 children 属性中包含一个对象,该对象表示每个嵌入框架的屏蔽状态。

例如:

{
  children: [
    {
      children: [],
      id: "iframe-id",
      name: "iframe-name",
      reasons: [],
      src: "./index.html",
      url: "https://www.example.com/"
    },
    {
      children: [],
      id: "iframe-id2",
      name: "iframe-name2",
      reasons: [
        {"reason": "unload-listener"}
      ],
      src: "./unload-examples.html",
      url: "https://www.example.com/unload-examples.html"
    },
  ],
  id: null,
  name: null,
  reasons: [],
  src: null,
  url:"https://www.example.com"
}

报告跨源框架中的 bfcache 屏蔽

如果网页嵌入了跨源框架,我们会限制分享的有关这些框架的信息量,以免泄露跨源信息。我们只会添加外部网页已知的信息,以及跨源子树是否阻止了 bfcache。我们不会提供任何屏蔽原因或关于子树下级的信息(即使某些子级是同源的)。

例如:

{
  children: [
    {
      children: [],
      id: "iframe-id",
      name: "iframe-name",
      reasons: [],
      src: "./index.html",
      url: "https://www.example2.com/"
    }
  ],
  id: null,
  name: null,
  reasons: [
        {"reason": "masked"}
  ],
  src: null,
  url:"https://www.example.com"
}

对于所有跨源 iframe,我们会将帧的 reasons 值报告为 null,并且顶级帧的理由将显示为 "masked"。请注意,"masked" 也可能出于特定于用户代理的原因而被使用,因此并不一定表示 iframe 中存在问题。

如需详细了解安全和隐私权注意事项,请参阅说明中的安全和隐私部分。

屏蔽原因

正如我们之前所说,导致屏蔽问题的原因有很多:

以下是无法使用 bfcache 的一些最常见原因示例:

  • unload-listener:网页注册了 unload 处理程序,这会阻止在某些浏览器中使用 bfcache。如需了解详情,请参阅弃用 unload 事件
  • response-cache-control-no-store:该页面使用 no-store 作为 cache-control 值。
  • related-active-contents:该网页是从另一个网页(使用“复制标签页”)打开的,而该网页仍引用了此网页。

反馈

Chromium 团队希望了解您使用 bfcache notRestoredReasons API 的体验。

请向我们说明 API 设计

API 是否有某些方面未按预期运行?或者,您是否缺少实现想法所需的方法或属性?对安全模型有疑问或意见?在相应的 GitHub 代码库中提交规范问题,或在现有问题中添加您的想法。

报告实现方面的问题

您是否发现了 Chromium 实现中的 bug?或者实现方式是否与规范不同? 请在我们的问题跟踪器上提交 bug。请务必提供尽可能详细的信息、简单的重现说明,并将组件指定为 UI > Browser > Navigation > BFCache故障非常适合分享快速简便的重现步骤。

显示对该 API 的支持

您打算使用 bfcache notRestoredReasons API 吗?您的公开支持有助于 Chromium 团队确定功能的优先级,并向其他浏览器供应商表明支持这些功能的重要性。

使用 #NotRestoredReasons 标签向 @ChromiumDev 发送推文,告诉我们您在哪里以及如何使用该工具。

实用链接