Usa WebSockets en service workers

En este instructivo, se muestra cómo conectarte a un WebSocket en el service worker de la extensión de Chrome. Puedes encontrar un ejemplo funcional en GitHub.

Información general

A partir de Chrome 116, los service workers de extensión obtienen compatibilidad mejorada con WebSockets. Anteriormente, un service worker podía estar inactivo a pesar de que una conexión de WebSocket estuviera activa si no se producían otros eventos de extensión durante 30 segundos. Esto finalizaría el service worker y cerraría la conexión de WebSocket. Para obtener más información sobre el ciclo de vida del service worker de extensión, consulta la guía del service worker de extensión.

A partir de Chrome 116, puedes mantener activa un service worker con una conexión de WebSocket activa el intercambio de mensajes dentro de la ventana de actividad del service worker de 30 s. Estas se pueden iniciar desde tu servidor o desde tu extensión. En el siguiente ejemplo, enviaremos un mensaje normal desde la extensión de Chrome al servidor para asegurarnos de que el service worker siga activo.

Ejemplo: keepalive de WebSocket

En primer lugar, debemos asegurarnos de que nuestra extensión solo se ejecute en versiones de Chrome compatibles con WebSockets en service workers. Para ello, debemos establecer la versión mínima de Chrome en 116 en el manifiesto:

manifest.json:

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

Luego, podemos mantener el service worker activo enviando un mensaje keepalive cada 20 s. El keepalive se inicia una vez que el service worker se conecta a WebSocket. El siguiente cliente de WebSocket de muestra registra mensajes y llama a keepAlive() cuando se activa el evento 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();
}

Dentro de keepAlive(), usamos setInterval(...) para enviar con regularidad un ping al servidor mientras haya una conexión de WebSocket activa:

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