Używanie WebSockets w skryptach service worker

W tym samouczku pokazujemy, jak nawiązać połączenie z WebSocket w skrypcie service worker rozszerzenia do Chrome. Działanie znajdziesz na GitHubie.

Wprowadzenie

Od wersji Chrome 116 mechanizmy Service Worker rozszerzenia są objęte ulepszoną obsługą WebSockets. Wcześniej mechanizm Service Worker mógł stać się nieaktywny nawet wtedy, gdy połączenie WebSocket było aktywne, jeśli przez 30 sekund nie występowały żadne inne zdarzenia rozszerzenia. Spowoduje to zamknięcie skryptu service worker i połączenie WebSocket. Więcej informacji na temat cyklu życia skryptu service worker rozszerzenia znajdziesz w przewodniku po takich skryptach.

Począwszy od wersji Chrome 116, możesz utrzymywać aktywność skryptu service worker z połączeniem WebSocket, wymieniając wiadomości w oknie aktywności mechanizmu Service Worker w wersji 30. Mogą one być inicjowane z Twojego serwera lub rozszerzenia. W poniższym przykładzie będziemy wysyłać zwykłą wiadomość z rozszerzenia Chrome na serwer, aby upewnić się, że skrypt service worker pozostanie aktywny.

Przykład: utrzymywanie aktywności przez WebSocket

Najpierw musimy się upewnić, że nasze rozszerzenie działa tylko w wersjach Chrome obsługujących WebSockets w skryptach service worker, ustawiając w pliku manifestu minimalną wersję Chrome na 116:

manifest.json:

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

Możemy wtedy utrzymywać aktywny mechanizm Service Worker, wysyłając wiadomość podtrzymującą aktywność co 20 s. Utrzymywanie aktywności jest uruchamiane po połączeniu skryptu service worker z WebSocket. Ten przykładowy klient WebSocket rejestruje wiadomości i wywołuje metodę keepAlive() po wywołaniu zdarzenia 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();
}

W obiekcie keepAlive() używamy setInterval(...) do regularnego wysyłania pingów do serwera, gdy jest aktywne 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 
  );
}