往返缓存 notRestoredReasons API

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

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

当前状态

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

概念和用法

新式浏览器为历史记录导航提供了一项名为往返缓存 (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 发送推文,告诉我们您在哪里以及如何使用该工具。

实用链接