Utilizzo di WebSocket nei service worker

Questo tutorial mostra come connettersi a un WebSocket nel service worker dell'estensione di Chrome. Puoi trovare un esempio funzionante su GitHub.

Contesto

A partire da Chrome 116, i service worker delle estensioni ricevono un supporto migliorato per WebSockets. In precedenza, un service worker poteva diventare inattivo nonostante una connessione WebSocket fosse attiva se non si verificavano altri eventi di estensione per 30 secondi. Questo comporta la terminazione del service worker e la connessione WebSocket. Per ulteriori informazioni sul ciclo di vita del service worker delle estensioni, leggi la guida dei service worker delle estensioni.

A partire da Chrome 116, puoi mantenere attiva un service worker con una connessione WebSocket scambiando messaggi nella finestra di attività del service worker di 30 secondi. Possono essere avviate dal server o dall'estensione. Nel seguente esempio, invieremo un normale messaggio dall'estensione di Chrome al server per garantire che il service worker resti attivo.

Esempio: keepalive WebSocket

Innanzitutto dobbiamo assicurarci che la nostra estensione venga eseguita solo nelle versioni di Chrome che supportano WebSocket nei service worker, impostando la versione minima di Chrome su 116 nel manifest:

manifest.json:

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

Possiamo quindi mantenere attivo il service worker inviando un messaggio keepalive ogni 20 secondi. Il keepalive viene avviato una volta che il service worker si connette a WebSocket. Il seguente client WebSocket di esempio registra i messaggi e chiama keepAlive() quando viene attivato l'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();
}

All'interno di keepAlive() utilizziamo setInterval(...) per inviare regolarmente un ping al server quando è presente una connessione WebSocket attiva:

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