Utiliser WebSockets dans les service workers

Ce tutoriel explique comment se connecter à un WebSocket dans le service worker de votre extension Chrome. Vous trouverez un exemple fonctionnel sur GitHub.

Contexte

À partir de Chrome 116, les service workers d'extension bénéficient d'une meilleure compatibilité avec WebSockets. Auparavant, un service worker pouvait devenir inactif même si une connexion WebSocket était active si aucun autre événement d'extension ne se produisait pendant 30 secondes. Cette action met fin au service worker et ferme la connexion WebSocket. Pour en savoir plus sur le cycle de vie des workers d'extensions, consultez le guide des services d'extension.

À partir de Chrome 116, vous pouvez conserver un service worker disposant d'une connexion WebSocket actif en échangeant des messages dans la fenêtre d'activité du service worker de 30 secondes. Celles-ci peuvent être lancées depuis votre serveur ou depuis votre extension. Dans l'exemple suivant, nous envoyons un message standard de l'extension Chrome au serveur pour nous assurer que le service worker reste actif.

Exemple: message keepalive WebSocket

Tout d'abord, nous devons nous assurer que l'extension ne s'exécute que dans les versions de Chrome compatibles avec WebSockets par les service workers. Pour ce faire, définissez la version minimale de Chrome sur 116 dans le fichier manifeste:

manifest.json:

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

Nous pouvons ensuite maintenir le service worker actif en envoyant un message keepalive toutes les 20 secondes. Le message keepalive est lancé une fois que le service worker s'est connecté à WebSocket. L'exemple de client WebSocket suivant consigne les messages et appelle keepAlive() lorsque l'événement onopen est déclenché:

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

Dans keepAlive(), nous utilisons setInterval(...) pour envoyer régulièrement un ping au serveur lorsqu'une connexion WebSocket est active:

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