在 Service Worker 中使用 WebSocket

本教學課程說明如何在 Chrome 擴充功能的 Service Worker 中連線至 WebSocket。如要查看實際使用範例,請前往 GitHub

背景

從 Chrome 116 開始,擴充功能服務工作站將針對 WebSockets 改善支援。過去,如果 WebSocket 連線持續運作 30 秒,服務工作處理程序就會變成閒置狀態,這麼做會終止 Service Worker,並關閉 WebSocket 連線。如要進一步瞭解擴充功能服務工作站生命週期的背景資訊,請參閱擴充功能 Service Worker 指南

從 Chrome 116 開始,您可以在 30 秒的 Service Worker 活動視窗中交換訊息,藉此讓 Service Worker 啟用 WebSocket 連線。指令碼可以透過您的伺服器或擴充功能啟動。在以下範例中,我們會從 Chrome 擴充功能傳送一般訊息至伺服器,確保 Service Worker 有效運作。

範例:WebSocket keepalive

首先,我們需要確保擴充功能只在支援服務工作人員的 Chrome 版本中執行,方法是在資訊清單中將 Chrome 最低版本設為 116:

manifest.json:

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

然後,我們每隔 20 秒傳送一次保持運作訊息,確保服務工作處理程序保持啟用狀態。當 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 
  );
}