要点:Extensions API 已更新,可支持往返缓存, 预加载导航。有关详情,请参阅下文。
Chrome 一直致力于提高导航速度。即时导航 往返缓存等技术 (在桌面设备上提供, Chrome 96)和推测规则 (在 Chrome 103 中提供)改进了过往和未来 体验在这篇博文中,我们将探讨我们对浏览器的更新 扩展 API 来适应这些新工作流。
了解网页类型
在引入往返缓存和预渲染之前, 标签页只有一个活动页面。这始终是可见项。如果 当用户返回上一页时,活动页面将被销毁(页面 B) 历史记录中的前一页将会被完全重建(网页 A)。 扩展程序无需担心生命周期页面的哪个部分 因为一个标签页只有一个对应的元素,即活动/可见状态。
![逐出活跃页面](https://developer.chrome.google.cn/static/blog/extension-instantnav/image/eviction-the-active-page-28eaaebd9549a.png?authuser=8&hl=da)
有了往返缓存和预渲染功能,您便无需再一对一 标签页和页面之间的关系。现在,每个标签页实际上 页面和页面会在不同状态之间转换,而不会被销毁并
例如,网页一开始可以显示为预渲染(不可见)的网页, 会在用户点击链接时转到活动(可见)页面,然后 会存储在往返缓存中(不可见) 而无需销毁另一个页面。本文后面的部分 我们将介绍一些新增的属性,以帮助附加信息了解 页面所处的状态
![网页类型](https://developer.chrome.google.cn/static/blog/extension-instantnav/image/types-pages-5bed5a04836ba.png?authuser=8&hl=da)
请注意,一个标签页可以有一系列预渲染的网页(而不只是一个), 活动(可见)网页,以及一系列往返缓存网页。
对于扩展程序开发者来说,会有哪些变化?
框架 ID == 0
在 Chromium 中,我们将最顶层/主框架称为最外层的框架。
采用 frameId 的扩展程序作者
为 0(之前的最佳做法)可能会出现问题。
由于一个标签页现在可以有多个最外层的帧(预渲染和缓存的帧)
网页),则假设有一个最外层的
错误。frameId == 0
仍将继续代表
活动页面最外层的框架,但
同一标签页中的其他页面将为非零值。新字段 frameType 包含
以解决此问题。有关详情,请参阅“如何确定某个帧是否为最外层的帧?”
部分。
框架与文档的生命周期
扩展程序会有问题的另一个概念是 帧。框架托管一个文档(该文档与提交的网址相关联)。 文档可以更改(例如通过导航),但 frameId 不会,因此它 难以将特定文档中发生的事情与 frameIds 中。我们引入了 documentId 的概念 每个文档的唯一标识符。如果在帧中导航时 会打开一个新文档,其中的标识符会更改。此字段对于以下情况非常有用: 确定网页何时更改其生命周期状态 prerender/active/cached),因为它保持不变。
网页导航事件
chrome.webNavigation
命名空间中的事件
可以在
具体取决于其所处的生命周期。请参阅
“如何判断网页处于哪个生命周期?”
和“如何确定页面何时转换?”部分。
如何判断网页处于哪个生命周期?
DocumentLifecycle
类型已添加到一些扩展程序 API,其中 frameId
是
。如果事件中存在 DocumentLifecycle
类型
(例如 onCommitted
)、
其值是生成事件时所处的状态。您可以随时查询
来自WebNavigation
getFrame()
的信息
和getAllFrames()
方法,但始终建议使用 事件的值。如果您确实要使用
但这两种方法都知道,在事件发生之前,帧的状态可能会发生变化。
生成之后,并且这两个方法返回的 promise 都已得到解析。
DocumentLifecycle
具有以下值:
"prerender
英寸:当前未向用户显示,但正在准备向用户显示。"active"
:目前向用户显示。"cached"
:存储在往返缓存中。"pending_deletion"
:正在销毁文档。
如何确定某个帧是否为最外层的帧?
之前,扩展程序可能会检查 frameId == 0
,以确定
如果事件是否发生在最外层的帧中,则会发生此错误。包含多个页面
在标签页中,我们现在有多个最外层的帧,因此 frameId 的定义
存在问题。您永远不会收到有关往返缓存的事件
帧。不过,对于预渲染的帧,frameId
非零值。因此,使用 frameId == 0
作为
以确定它是否是最外层的帧是错误的。
为帮助解决此问题,我们引入了一种名为
FrameType
因此,现在可以轻松确定帧是否确实是最外层的帧。
FrameType
具有以下值:
"outermost_frame"
:通常称为最顶层帧。请注意, 其中有好几种。例如,如果您有预渲染和缓存的 每个页面都有一个最外层的框架,可以称为其最顶部的框架。"fenced_frame"
:预留以备将来使用。"sub_frame"
:通常是 iframe。
我们可以结合使用 DocumentLifecycle
和 FrameType
,确定某个帧是否
处于活动状态的最外层帧。例如:tab.documentLifecycle === “active” && frameType === “outermost_frame”
。
如何解决帧的使用时间问题?
正如上文所述,框架托管了一个文档,该框架可能会导航到新的
但 frameId
不会改变。这会造成一些问题,
收到一个仅包含 frameId
的事件。如果您查询网址
它可能与事件发生时不同,这称为
使用时间问题
为解决这一问题,我们推出了 documentId
(以及 parentDocumentId
)。
webNavigation.getFrame()
如果提供了 documentId
,方法现在会将 frameId
设置为可选。通过
每次浏览帧时,documentId
都会更改。
如何确定网页何时转换?
有显式信号可确定网页何时在不同状态间转换。
我们来看看 WebNavigation
事件。
首次浏览任何网页时,您会看到
。请注意,使用
DocumentLifecycle
状态为 "prerender"
或 "active"
。
onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted
如下图所示,documentId
会随着
更改为 "xyz"
。
![当预渲染的页面成为活动页面时,documentId 会发生变化](https://developer.chrome.google.cn/static/blog/extension-instantnav/image/the-documentid-changes-t-6afaa608cddf7.png?authuser=8&hl=da)
documentId
活动页面。当网页从往返缓存或预渲染转换为
那么还有三个事件(但 DocumentLifecyle
为 "active"
)。
onBeforeNavigate
onCommitted
onCompleted
documentId
将与原始事件中相同。这是
如上图所示,当 documentId
== xyz 激活时。请注意,
会触发相同的导航事件,但 onDOMContentLoaded
除外
事件,因为该网页已加载完毕。