往返缓存 notRestoredReasons API

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

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

当前状态

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

概念和用法

现代浏览器提供了一种针对历史记录导航的优化功能,称为往返缓存 (bfcache)。这样,当用户返回之前访问过的网页时,就能获得即时加载体验。网页在 bfcache 中可能会由于各种原因而被屏蔽或被逐出,有些是规范要求的,有些则特定于浏览器实现。

以前,尽管 Chrome 开发者工具中提供了一项测试,但开发者无法找出其网页被禁止在该字段中使用 bfcache 的原因。为了在字段中启用监控功能,我们扩展了 PerformanceNavigationTiming 类,以包含 notRestoredReasons 属性。这将返回一个对象,其中包含顶部框架和文档中存在的所有 iframe 的相关信息:

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

    这样一来,开发者就可以采取行动使这些网页与 bfcache 兼容,从而提高网站性能。

示例

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

例如,您可以调用以下函数来返回性能时间轴中存在的所有 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。请务必包含尽可能多的细节信息以及有关重现的简单说明,并将组件指定为 UI > Browser > Navigation > BFCacheGlitch 非常适用于分享轻松快速的重现问题。

表示对 API 的支持

您是否打算使用 bfcache notRestoredReasons API?您的公开支持可帮助 Chromium 团队确定功能的优先级,并向其他浏览器供应商展示支持这些功能的重要性。

使用 # 标签 #NotRestoredReasons@ChromiumDev 发送一条推文,告诉我们您使用它的位置和方式。

实用链接