Używanie WebSockets w skryptach service worker

Z tego samouczka dowiesz się, jak połączyć się z WebSocketem w skrypcie service worker rozszerzenia Chrome. Działający przykład znajdziesz na GitHubie.

Tło

Od Chrome 116 pracownicy usług rozszerzeń mają lepszą obsługę WebSockets. Wcześniej skrypt service worker mógł stać się nieaktywny pomimo aktywnego połączenia WebSocket, jeśli przez 30 sekund nie wystąpiły żadne inne zdarzenia rozszerzenia. Spowoduje to zakończenie działania skryptu service worker i zamknięcie połączenia WebSocket. Więcej informacji o cyklu życia skryptu service worker rozszerzenia znajdziesz w przewodniku po skryptach service worker rozszerzeń.

Od Chrome 116 możesz utrzymywać aktywność skryptu service worker z połączeniem WebSocket, wymieniając wiadomości w 30-sekundowym oknie aktywności skryptu service worker. Można je inicjować z serwera lub z rozszerzenia. W poniższym przykładzie wyślemy zwykłą wiadomość z rozszerzenia do Chrome na serwer, aby upewnić się, że skrypt service worker pozostanie aktywny.

Przykład: WebSocket keepalive

Najpierw musimy się upewnić, że nasze rozszerzenie działa tylko w wersjach Chrome obsługujących WebSockets w pracownikach usługi. W tym celu ustawiamy w pliku manifestu minimalną wersję Chrome na 116:

manifest.json:

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

Następnie możemy utrzymać aktywność komponentu Service Worker, wysyłając co 20 sekund wiadomość podtrzymującą połączenie. Funkcja utrzymywania aktywności jest uruchamiana, gdy skrypt service worker połączy się z protokołem WebSocket. Ten przykładowy klient WebSocket rejestruje wiadomości i wywołuje keepAlive(), gdy zostanie aktywowane zdarzenie 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();
}

keepAlive() używamy setInterval(...), aby regularnie wysyłać ping do serwera, gdy aktywne jest połączenie WebSocket:

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