了解哪些导航被阻止使用 bfcache,以及原因。
添加到 PerformanceNavigationTiming 类中的 notRestoredReasons 属性会报告以下信息:文档中呈现的帧在导航时是否被阻止使用 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,我们会针对相应帧的 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 发送推文,告诉我们您在何处以及如何使用它。