Chrome 扩展程序:扩展 API 以支持即时导航

Dave Tapuska
Dave Tapuska

要点:Extensions API 已更新,可支持往返缓存, 预加载导航。有关详情,请参阅下文。

Chrome 一直致力于提高导航速度。即时导航 往返缓存等技术 (在桌面设备上提供, Chrome 96)和推测规则 (在 Chrome 103 中提供)改进了过往和未来 体验在这篇博文中,我们将探讨我们对浏览器的更新 扩展 API 来适应这些新工作流。

了解网页类型

在引入往返缓存和预渲染之前, 标签页只有一个活动页面。这始终是可见项。如果 当用户返回上一页时,活动页面将被销毁(页面 B) 历史记录中的前一页将会被完全重建(网页 A)。 扩展程序无需担心生命周期页面的哪个部分 因为一个标签页只有一个对应的元素,即活动/可见状态。

逐出活跃页面
逐出活动页面。

有了往返缓存和预渲染功能,您便无需再一对一 标签页和页面之间的关系。现在,每个标签页实际上 页面和页面会在不同状态之间转换,而不会被销毁并

例如,网页一开始可以显示为预渲染(不可见)的网页, 会在用户点击链接时转到活动(可见)页面,然后 会存储在往返缓存中(不可见) 而无需销毁另一个页面。本文后面的部分 我们将介绍一些新增的属性,以帮助附加信息了解 页面所处的状态

网页类型
网页类型。

请注意,一个标签页可以有一系列预渲染的网页(而不只是一个), 活动(可见)网页,以及一系列往返缓存网页。

对于扩展程序开发者来说,会有哪些变化?

框架 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。

我们可以结合使用 DocumentLifecycleFrameType,确定某个帧是否 处于活动状态的最外层帧。例如: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 会发生变化
当预渲染的网页变为documentId 活动页面。

当网页从往返缓存或预渲染转换为 那么还有三个事件(但 DocumentLifecyle"active")。

onBeforeNavigate
onCommitted
onCompleted

documentId 将与原始事件中相同。这是 如上图所示,当 documentId == xyz 激活时。请注意, 会触发相同的导航事件,但 onDOMContentLoaded 除外 事件,因为该网页已加载完毕。

如果您有任何意见或问题,请随时在 chromium-extensions