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'extensions bénéficient d'une meilleure compatibilité avec WebSockets. Auparavant, un service worker pouvait devenir inactif malgré l'activation d'une connexion WebSocket 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 service workers d'extension, consultez le guide des service workers d'extension.

À partir de Chrome 116, vous pouvez maintenir un service worker avec une connexion WebSocket active en échangeant des messages dans la fenêtre d'activité du service worker de 30 secondes. Ils peuvent être lancés à partir de votre serveur ou de votre extension. Dans l'exemple suivant, nous enverrons un message régulier de l'extension Chrome au serveur pour nous assurer que le service worker reste actif.

Exemple : keepalive WebSocket

Nous devons d'abord nous assurer que l'extension ne s'exécute que dans les versions de Chrome compatibles avec WebSockets dans les service workers, en définissant 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 keepalive est lancé une fois que le service worker se connecte au 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 
  );
}