找出哪些导航被阻止使用 bfcache,以及原因。
notRestoredReasons 属性已添加到 PerformanceNavigationTiming 类中,用于报告文档中存在的框架是否在导航时被阻止使用 bfcache,以及原因。开发者可以利用这些信息来识别需要更新以使其与 bfcache 兼容的网页,从而提升网站性能。
当前状态
notRestoredReasons API 已从 Chrome 123 开始发布,并正在逐步推出。
概念和用法
现代浏览器提供了一项针对历史记录导航的优化功能,称为往返缓存 (bfcache)。这样,当用户返回到已访问过的网页时,便可获得即时加载体验。网页可能会因各种原因而无法进入 bfcache 或在 bfcache 中被逐出,其中一些原因是由规范要求的,另一些原因则特定于浏览器实现。
以前,开发者无法找出其网页在实际使用中无法使用 bfcache 的原因,尽管 Chrome 开发者工具中提供了测试。为了在现场进行监控,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,我们会报告该 iframe 的 reasons 值为 null,而顶级 iframe 将显示原因为 "masked"。请注意,"masked" 也可能用于用户代理特定的原因,因此不一定表示 iframe 中存在问题。
如需详细了解安全和隐私权方面的注意事项,请参阅说明文档中的安全和隐私权部分。
屏蔽原因
如前所述,导致阻塞的原因有很多:
以下是无法使用 bfcache 的一些最常见原因示例:
unload-listener:该网页注册了unload处理程序,这会阻止在某些浏览器中使用 bfcache。请注意,从 Chrome 155 开始,Chrome 不再发出此原因,除非网站已选择重新启用unload事件。如需了解详情,请参阅弃用 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 发送推文,告诉我们您在何处以及如何使用它。