Используйте WebSockets в сервис-воркерах

В этом руководстве показано, как подключиться к WebSocket в сервис-воркере вашего расширения Chrome. Рабочий пример можно найти на GitHub .

Фон

Начиная с Chrome 116, сервис-воркеры расширений получают улучшенную поддержку WebSocket . Ранее сервис-воркер мог стать неактивным, несмотря на активное соединение WebSocket, если в течение 30 секунд не происходило никаких других событий расширения. Это приводило к завершению работы сервис-воркера и закрытию соединения WebSocket. Для получения дополнительной информации о жизненном цикле сервис-воркера расширений ознакомьтесь с руководством по сервис-воркерам расширений .

Начиная с Chrome 116, вы можете поддерживать активность сервис-воркера с WebSocket-соединением, обмениваясь сообщениями в течение 30-секундного окна активности сервис-воркера. Эти сообщения могут инициироваться либо вашим сервером, либо вашим расширением. В следующем примере мы будем отправлять обычное сообщение из расширения Chrome на сервер, чтобы гарантировать, что сервис-воркер останется активным.

Пример: протокол WebSocket keepalive

Для начала нам нужно убедиться, что наше расширение работает только в тех версиях Chrome, которые поддерживают WebSockets в сервис-воркерах, установив минимальную версию Chrome на 116 в манифесте:

manifest.json:

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

Затем мы можем поддерживать активность сервис-воркера, отправляя сообщение keepAlive каждые 20 секунд. KeepAlive запускается, как только сервис-воркер подключается к WebSocket. Следующий пример клиента WebSocket регистрирует сообщения и вызывает keepAlive() при срабатывании события onopen :

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() мы используем setInterval(...) для регулярной отправки пинга на сервер, пока существует активное WebSocket-соединение:

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 
  );
}