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.

Sfondo

A partire da Chrome 116, i worker di servizio delle estensioni ricevono un supporto migliorato per i WebSocket. 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. In questo modo il service worker viene terminato e la connessione WebSocket viene chiusa. Per ulteriori informazioni sul ciclo di vita del service worker dell'estensione, leggi la guida al service worker dell'estensione.

A partire da Chrome 116, puoi mantenere attiva un service worker con una connessione WebSocket scambiando messaggi entro la finestra di attività dei service worker entro 30 secondi. Queste possono essere avviate dal tuo server o dalla tua estensione. Nell'esempio seguente, invieremo un messaggio normale dall'estensione di Chrome al server per assicurarci che il service worker rimanga attivo.

Esempio: keepalive WebSocket

Per prima cosa dobbiamo assicurarci che la nostra estensione sia eseguita solo nelle versioni di Chrome che supportano WebSocket nei service worker impostando la versione minima di Chrome su 116 nel file manifest:

manifest.json:

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

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