针对扩展消息端口的 BFCache 行为做出了变更

往返缓存(简称 BFCache)是一种浏览器优化解决方案,可实现即时的往返导航。我们即将对 Chrome BFCache 做出更改,这可能会影响使用邮件端口的扩展程序。如果您拥有的 Chrome 扩展程序使用消息功能在内容脚本和扩展程序之间通信,请继续阅读下文,了解如何测试和调整您的扩展程序。

扩展程序消息端口

扩展程序通过消息传递与内容脚本或其他扩展程序进行通信。您可以通过调用 runtime.sendMessage()tabs.sendMessage(),或使用可重复使用的消息端口,使用一次性请求发送消息。只要该端口处于活动状态,内容脚本和扩展程序后台脚本都可以重复使用该端口来互相发布消息。

如需了解详情,请参阅消息传递

往返缓存

当用户离开符合 BFCache 使用条件的网页时,浏览器会允许该网页及其所有状态始终保留在内存中,但处于非完全活跃状态。如果用户执行历史记录导航(向后或向前)前往缓存的网页,浏览器将尝试从 BFCache 恢复该网页。这样可以提高导航速度,并改善用户的浏览体验。

当该网页在 BFCache 中时,它处于冻结状态,不允许执行任何 JavaScript。这意味着它无法处理收到的消息。

如需了解详情,请参阅往返缓存

扩展消息端口对 BFCache 的影响

简而言之,扩展程序将消息发送到 BFCache 中的页面可能会导致缓存逐出并影响性能。

如果将具有开放扩展程序消息端口的网页存储在 BFCache 中,该端口将保持开启状态。从 BFCache 恢复页面后,扩展 Service Worker 仍可使用消息端口的旧引用将消息发布到内容脚本。

但是,如果扩展程序在网页仍在 BFCache 中时尝试通过该消息端口发布消息,则消息发送后就无法完全递送,因为处理程序会冻结。扩展对这种情况进行推理和解决颇具挑战性,因为消息的排队和丢弃都有各自的问题。

为避免遇到与丢失消息相关的问题,在 Chrome 的当前实现中,它会从 BFCache 中逐出主机页面并舍弃消息。如果用户返回该网页,系统将重新加载该网页,以便扩展程序设置新的连接。

另一方面,此实现会限制 BFCache 适用的场景,从而限制性能提升,尤其是对于具有广播或检测信号机制的扩展程序,该机制会定期向所有连接发送消息。此外,由于系统会在扩展程序向内容脚本发送消息时触发逐出操作,因此 Web 开发者无法阻止自己的网页被逐出。

为了提高整体性能,我们计划引入一种新的消息端口行为。

新行为:页面存储在 BFCache 中时关闭消息通道

从 Chrome 123 开始,当具有开放扩展程序消息端口的网页存储在 BFCache 中时,底层消息通道会从内容脚本端主动关闭。届时,所有消息端口都将关闭,且该扩展程序会收到 onDisconnect 事件。

由于通道已关闭,因此当页面位于 BFCache 中时,系统不会向其发送任何消息。因此,该网页不会因为延期而被逐出。

即使网页已从 BFCache 恢复,关闭的消息通道也不会重新打开。建议扩展程序开发者监听页面生命周期事件,并在页面从 BFCache 恢复时设置新连接,如下例所示。

// content script

let port;

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // The page is restored from BFCache, set up a new connection.
    port = chrome.runtime.connect();
  }
});

详细了解不同浏览器代表的 WECG 对话(受问题 474 影响)。

我会受到影响吗?

在 Chrome 123 中,新行为将包含在标记后面,以便您测试代码。如需了解详情,请参阅时间表。按照以下步骤测试您的扩展程序。请注意,此测试仅提供简单的测试,因此我们建议您在启用该功能后运行 Chrome 一段时间,因为很难预测该扩展程序中的哪些功能可能会导致问题。

  1. 请确保 Chrome 版本至少为 123。理想情况下,请使用 Chrome Canary 版,它会提供额外的警告信息,以简化测试。
  2. 使用以下 flag 启动 Chrome:

    --disable-features=DisconnectExtensionMessagePortWhenPageEntersBFCache
    
  3. 在扩展程序未运行的情况下,访问符合 BFCache 使用条件的网页(例如,https://example.com/ 等简单网站)。按照 BFCache 教程操作,确保它从 BFCache 中恢复。

  4. 安装并启用扩展程序,然后再次测试 BFCache 资格。您可以手动离开,等待扩展程序将消息发布到 BFCached 页面,然后返回。

  5. 如果由于逐出而必须重新加载页面而不是从 BFCache 加载,并且阻止恢复的问题为“ExtensionSentMessageToCachedFrame”,则扩展程序可能会受到此更改的影响。

    在 Chrome Canary 124.0.6315.0 及更高版本中,您还会在页面中看到以下警告:

    未能从 BFCache 恢复网页时显示的警告。
    未从 BFCache 恢复页面时显示的警告。

确认该扩展程序正在将消息发布到 BFCache 页面后,您可以按照以下步骤强制启用实验,并观察是否有任何逻辑中断。

  1. 使用以下 flag 启动 Chrome:

    --enable-features=DisconnectExtensionMessagePortWhenPageEntersBFCache
    
  2. 前往因“ExtensionSentMessageToCachedFrame”而未从 BFCache 恢复的页面。

  3. 先离开,再返回。该网页现在应该已恢复,但内容脚本与 Service Worker 之间的消息通道应该已断开。

  4. 测试扩展程序是否仍可照常运行;如果没有,则应按照上一部分中所示手动重新连接。

发布时间表

我们计划从 Chrome 123 开始逐步推广这一新行为。以下是详细计划:

日期 计划的里程碑
2 月 15 日 开始实验 Chrome Canary 版和开发者版中的新行为。
3 月 1 日 开始实验 Chrome Beta 版的新行为。
3 月 18 日 在 Chrome 稳定版中向 4% 的用户发布新行为。
3 月 25 日 在 Chrome 稳定版中向 50% 的用户发布新行为。
4 月 2 日 实验结束,使新行为成为默认行为。