WebSockets in Service Workern verwenden

In dieser Anleitung wird gezeigt, wie Sie eine Verbindung zu einem WebSocket im Service Worker Ihrer Chrome-Erweiterung herstellen. Ein funktionierendes Beispiel finden Sie auf GitHub.

Hintergrund

Ab Chrome 116 wird die Unterstützung für WebSockets in Service Workern von Erweiterungen verbessert. Bisher konnte ein Service Worker inaktiv werden, obwohl eine WebSocket-Verbindung aktiv war, wenn 30 Sekunden lang keine anderen Erweiterungsereignisse aufgetreten sind. Dadurch wurde der Service Worker beendet und die WebSocket-Verbindung geschlossen. Weitere Informationen zum Lebenszyklus von Service Workern für Erweiterungen finden Sie im Leitfaden zu Service Workern für Erweiterungen.

Ab Chrome 116 können Sie einen Service Worker mit einer WebSocket-Verbindung aktiv halten, indem Sie innerhalb des 30-Sekunden-Aktivitätsfensters des Service Workers Nachrichten austauschen. Diese können entweder von Ihrem Server oder von Ihrer Erweiterung initiiert werden. Im folgenden Beispiel senden wir eine reguläre Nachricht von der Chrome-Erweiterung an den Server, um sicherzustellen, dass der Service Worker aktiv bleibt.

Beispiel: WebSocket-Keepalive

Zuerst müssen wir dafür sorgen, dass unsere Erweiterung nur in Chrome-Versionen ausgeführt wird, die WebSockets in Service Workern unterstützen. Dazu legen wir in der Manifestdatei die Mindestversion von Chrome auf 116 fest:

manifest.json:

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

Dann können wir den Service Worker aktiv halten, indem wir alle 20 Sekunden eine Keepalive-Nachricht senden. Der Keepalive wird gestartet, sobald der Service Worker eine Verbindung zum WebSocket herstellt. Der folgende WebSocket-Client protokolliert Nachrichten und ruft keepAlive() auf, wenn das Ereignis onopen ausgelöst wird:

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

In keepAlive() verwenden wir setInterval(...), um regelmäßig einen Ping an den Server zu senden, solange eine aktive WebSocket-Verbindung besteht:

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