Rozgłaszaj aktualizacje stron z skryptami service worker

Andrew Guan
Andrew Guan

W niektórych sytuacjach mechanizm Service Worker musi aktywnie komunikować się z dowolną z kontrolowanych kart, aby poinformować o określonym zdarzeniu. Przykłady:

  • Powiadomienie strony o zainstalowaniu nowej wersji skryptu service worker, tak aby użytkownik mógł zobaczyć przycisk „Zaktualizuj, aby odświeżyć” umożliwiający natychmiastowy dostęp do nowej funkcji.
  • Poinformuj użytkownika o zmianie w danych w pamięci podręcznej po stronie skryptu service worker, pokazując na przykład takie oznaczenie: „Aplikacja jest teraz gotowa do pracy w trybie offline” lub „Dostępna nowa wersja treści”.
Diagram przedstawiający mechanizm Service Worker komunikujący się ze stroną, aby wysłać aktualizację.

Takie przypadki użycia nazywamy „aktualizacjami strumieniowymi”, dzięki którym mechanizm Service Worker nie potrzebuje komunikatu ze strony, aby rozpocząć komunikację. W tym przewodniku omówimy różne sposoby wdrażania tego typu komunikacji między stronami a mechanizmami Service Worker przy użyciu standardowych interfejsów API przeglądarki i biblioteki Workbox.

Przypadki produkcyjne

Tinder

PWA Tinder używa workbox-window, aby nasłuchiwać ważnych momentów cyklu życia skryptu service worker z strony („zainstalowano”, „kontrolowana” i „aktywowano”). Dzięki temu, gdy nowy skrypt service worker pojawia się, wyświetla się baner „Aktualizacja dostępna”, aby można było odświeżyć aplikację PWA i uzyskać dostęp do najnowszych funkcji:

Zrzut ekranu z funkcją „Dostępna aktualizacja” aplikacji internetowej Tindera.
W aplikacji PWA Tinder skrypt service worker informuje stronę, że nowa wersja jest gotowa, a na stronie pojawia się baner „Aktualizacja dostępna”.

Dynia

Gdy skrypt Squoosh PWA zapisze w pamięci podręcznej wszystkie zasoby niezbędne do działania w trybie offline, wysyła na stronę komunikat „Gotowe do pracy w trybie offline”, który informuje użytkownika o tej funkcji:

Zrzut ekranu z aplikacją internetową Squoosh „Gotowa do pracy w trybie offline”.
W Squoosh PWA skrypt service worker rozsyła aktualizację do strony, gdy pamięć podręczna jest gotowa. Na stronie pojawia się komunikat „Gotowe do pracy w trybie offline”.

Korzystanie z Workbox

Nasłuchiwanie zdarzeń cyklu życia skryptu service worker

workbox-window ma prosty interfejs umożliwiający wychwytywanie ważnych zdarzeń cyklu życia skryptu service worker. Biblioteka używa interfejsów API po stronie klienta, takich jak updatefound i statechange, oraz udostępnia detektor zdarzeń wyższego poziomu w obiekcie workbox-window, co ułatwia użytkownikowi korzystanie z tych zdarzeń.

Ten kod strony pozwala wykryć każdą nową wersję skryptu service worker, by przekazać ją użytkownikowi:

const wb = new Workbox('/sw.js');

wb.addEventListener('installed', (event) => {
  if (event.isUpdate) {
    // Show "Update App" banner
  }
});

wb.register();

Poinformuj stronę o zmianach w danych pamięci podręcznej

Pakiet Workbox workbox-broadcast-update to standardowy sposób powiadamiania klientów okien o zaktualizowaniu odpowiedzi zapisanej w pamięci podręcznej. Ta metoda jest najczęściej używana w połączeniu ze strategią StaleGdyRevalidate.

Aby transmitować aktualizacje, dodaj broadcastUpdate.BroadcastUpdatePlugin do opcji strategii po stronie skryptu service worker:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';

registerRoute(
  ({url}) => url.pathname.startsWith('/api/'),
  new StaleWhileRevalidate({
    plugins: [
      new BroadcastUpdatePlugin(),
    ],
  })
);

W aplikacji internetowej możesz nasłuchiwać tych zdarzeń, na przykład:

navigator.serviceWorker.addEventListener('message', async (event) => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.data.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;

    // Do something with cacheName and updatedUrl.
    // For example, get the cached content and update
    // the content on the page.
    const cache = await caches.open(cacheName);
    const updatedResponse = await cache.match(updatedUrl);
    const updatedText = await updatedResponse.text();
  }
});

Korzystanie z interfejsów API przeglądarek

Jeśli funkcje dostarczane przez Workbox nie wystarczają do Twoich potrzeb, możesz wdrożyć „aktualizacje transmisji” za pomocą tych interfejsów API przeglądarki:

Interfejs Broadcast Channel API

Skrypt service worker tworzy obiekt BroadcastChannel i wysyłać do niego wiadomości. Każdy kontekst (np. strona) zainteresowany odebraniem tych wiadomości może utworzyć instancję BroadcastChannel i wdrożyć moduł obsługi wiadomości do odbierania wiadomości.

Aby poinformować stronę o instalowaniu nowego skryptu service worker, użyj tego kodu:

// Create Broadcast Channel to send messages to the page
const broadcast = new BroadcastChannel('sw-update-channel');

self.addEventListener('install', function (event) {
  // Inform the page every time a new service worker is installed
  broadcast.postMessage({type: 'CRITICAL_SW_UPDATE'});
});

Strona odsłuchuje te zdarzenia, subskrybując sw-update-channel:

// Create Broadcast Channel and listen to messages sent to it
const broadcast = new BroadcastChannel('sw-update-channel');

broadcast.onmessage = (event) => {
  if (event.data && event.data.type === 'CRITICAL_SW_UPDATE') {
    // Show "update to refresh" banner to the user.
  }
};

Jest to prosta technika, ale jej ograniczeniem jest obsługa przeglądarek: w tej chwili Safari nie obsługuje tego interfejsu API.

Interfejs API klienta

Interfejs Client API zapewnia prosty sposób komunikacji z wieloma klientami z poziomu skryptu service worker przez powtarzanie tablicy obiektów Client.

Użyj tego kodu skryptu service worker, aby wysłać wiadomość do ostatniej zaznaczonej karty:

// Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
  if (clients && clients.length) {
    // Respond to last focused tab
    clients[0].postMessage({type: 'MSG_ID'});
  }
});

Strona ma wbudowany moduł obsługi wiadomości, który przechwytuje te wiadomości:

// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
     if (event.data && event.data.type === 'MSG_ID') {
         // Process response
   }
};

Interfejs API klienta doskonale sprawdza się w przypadkach takich jak przekazywanie informacji do wielu aktywnych kart. Interfejs API jest obsługiwany przez wszystkie popularne przeglądarki, ale nie wszystkie jego metody są w niej obsługiwane. Zanim z niej skorzystasz, sprawdź jej obsługę.

Kanał wiadomości

Kanał wiadomości wymaga wstępnej konfiguracji, czyli przekazania portu ze strony do skryptu service worker w celu nawiązania między nimi kanału komunikacji. Strona tworzy instancję obiektu MessageChannel i przekazuje port do skryptu service worker przez interfejs postMessage():

const messageChannel = new MessageChannel();

// Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
  messageChannel.port2,
]);

Strona nasłuchuje wiadomości, implementując moduł obsługi „onmessage” na tym porcie:

// Listen to messages
messageChannel.port1.onmessage = (event) => {
  // Process message
};

Skrypt service worker odbiera port i zapisuje do niego odniesienie:

// Initialize
let communicationPort;

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'PORT_INITIALIZATION') {
    communicationPort = event.ports[0];
  }
});

Od tego momentu może wysyłać wiadomości na stronę, wywołując postMessage() w odniesieniu do portu:

// Communicate
communicationPort.postMessage({type: 'MSG_ID' });

Implementacja MessageChannel może być bardziej złożona ze względu na potrzebę inicjowania portów, ale jest obsługiwana przez wszystkie główne przeglądarki.

Dalsze kroki

W tym przewodniku omawiamy jeden konkretny przypadek komunikacji Window to Service Worker: „aktualizacje w transmisji”. Obejmuje to nasłuchiwanie ważnych zdarzeń cyklu życia mechanizmów Service Worker i komunikowanie się ze stroną na temat zmian w treści lub danych w pamięci podręcznej. Możesz rozważyć bardziej interesujące przypadki użycia, w których skrypt service worker aktywnie komunikuje się ze stroną, ale nie otrzymuje wcześniej żadnych komunikatów.

Więcej wzorców komunikacji między oknami i skryptami service worker znajdziesz w tych dokumentach:

  • Przewodnik po buforowaniu: wywoływanie skryptu service worker ze strony w celu wcześniejszego buforowania zasobów (np. w sytuacjach pobierania z wyprzedzeniem).
  • Dwukierunkowa komunikacja: przekazywanie zadania skryptowi service worker (np. bardzo intensywne pobieranie) i informowanie strony o postępach.

Dodatkowe materiały