查找哪些导航被禁止使用 bfcache,以及原因。
添加到 PerformanceNavigationTiming 类中的 notRestoredReasons 属性会报告文档中存在的帧在导航时是否被阻止使用 bfcache,以及原因。开发者可以使用这些信息来确定哪些网页需要更新以使其与 bfcache 兼容,从而提升网站性能。
当前状态
notRestoredReasons API 已从 Chrome 123 开始提供,并正在逐步推出。
概念和用法
新式浏览器为历史记录导航提供了一项名为往返缓存 (bfcache) 的优化功能。这样,当用户返回到之前访问过的网页时,即可获得即时加载体验。网页可能会因各种原因而被阻止进入 bfcache 或在 bfcache 中被驱逐,其中一些原因是规范要求的,一些原因则特定于浏览器实现。
以前,虽然有 Chrome 开发者工具中的测试,但开发者无法了解其网页在现场被禁止使用 bfcache 的原因。为了在现场启用监控功能,PerformanceNavigationTiming 类已扩展为包含 notRestoredReasons 属性。这会返回一个对象,其中包含有关顶级框架和文档中所有 iframe 的相关信息:
- 被禁止使用 bfcache 的原因。
框架
id和name等详细信息,有助于识别 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 发送推文,告诉我们您在哪里以及如何使用该工具。