Używanie WebSockets w skryptach service worker

W tym samouczku pokazujemy, jak nawiązać połączenie z WebSocket w usługowym workerze rozszerzenia Chrome. Przykład działania znajdziesz na GitHubie.

Tło

Począwszy od Chrome 116 mechanizmy Service Worker rozszerzenia będą mogły korzystać z ulepszonej obsługi protokołu 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 service worker i zamknięcie połączenia WebSocket. Więcej informacji na temat cyklu życia instancji roboczych usługi rozszerzenia znajdziesz w przewodniku po instancjach roboczych usługi rozszerzenia.

Począwszy od Chrome 116, możesz utrzymać aktywny skrypt service worker z połączeniem WebSocket, wymieniając wiadomości w ramach okna aktywności skryptu service worker. Można je zainicjować na serwerze lub w rozszerzeniu. W poniższym przykładzie wyślemy zwykłą wiadomość z rozszerzenia do Chrome na serwer, aby upewnić się, że skrypt service worker żyje.

Przykład: utrzymanie aktywności WebSocket

Najpierw musimy upewnić się, ż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",
  ...
}

Następnie możemy utrzymać aktywnego pracownika usługi, wysyłając wiadomość keepalive co 20 sekund. Usługa keepalive jest uruchamiana, gdy usługa robocza nawiązuje połączenie z WebSocket. Następujący przykładowy klient WebSocket rejestruje komunikaty i wywołuje 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 keepAlive() używamy protokołu 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 
  );
}