在 Service Worker 中使用 WebSocket

本教程演示了如何在 Chrome 扩展程序的 Service Worker 中连接到 WebSocket。您可以在 GitHub 上找到有效示例

背景

从 Chrome 116 开始,扩展程序 Service Worker 可以更好地支持 WebSockets。以前,如果在 30 秒内没有发生其他扩展事件,那么即使 WebSocket 连接处于活跃状态,Service Worker 也可能会变为非活跃状态。这会终止 Service Worker 并关闭 WebSocket 连接。有关扩展 Service Worker 生命周期的更多背景信息,请参阅扩展 Service Worker 指南

从 Chrome 116 开始,您可以通过在 30 秒的 Service Worker 活动窗口中交换消息,使具有 WebSocket 连接的 Service Worker 保持活动状态。这些操作可以从您的服务器启动,也可以从您的扩展程序启动。在以下示例中,我们将从 Chrome 扩展程序向服务器发送一条常规消息,以确保 Service Worker 保持活动状态。

示例:WebSocket keepalive

首先,我们需要在清单中将最低 Chrome 版本设置为 116,以确保我们的扩展程序仅在支持 Service Worker 中 WebSocket 的 Chrome 版本中运行:

manifest.json:

{
 
...
 
"minimum_chrome_version": "116",
 
...
}

然后,我们可以通过每 20 秒发送一条 keepalive 消息来使 Service Worker 保持活动状态。keepalive 会在 Service Worker 连接到 WebSocket 后启动。以下示例 WebSocket 客户端会记录消息,并在 onopen 事件触发时调用 keepAlive()

service-worker.js

let webSocket = null;

function connect() {
  webSocket
= new WebSocket('wss://example.com/ws');

  webSocket
.onopen = (event) => {
    console
.log('websocket open');
    keepAlive
();
 
};

  webSocket
.onmessage = (event) => {
    console
.log(`websocket received message: ${event.data}`);
 
};

  webSocket
.onclose = (event) => {
    console
.log('websocket connection closed');
    webSocket
= null;
 
};
}

function disconnect() {
 
if (webSocket == null) {
   
return;
 
}
  webSocket
.close();
}

keepAlive() 中,当 WebSocket 连接保持活跃状态时,我们使用 setInterval(...) 定期向服务器发送 ping:

function keepAlive() {
 
const keepAliveIntervalId = setInterval(
   
() => {
     
if (webSocket) {
        webSocket
.send('keepalive');
     
} else {
        clearInterval
(keepAliveIntervalId);
     
}
   
},
   
// Set the interval to 20 seconds to prevent the service worker from becoming inactive.
   
20 * 1000
 
);
}