Domyślnie cykl życia skryptu service worker wymaga, aby po znalezieniu i zainstalowaniu zaktualizowanego skryptu service worker wszystkie otwarte karty kontrolowane przez bieżący skrypt service worker były zamknięte lub poddawane nawigacji, zanim zaktualizowany skrypt service worker aktywuje się i przejmie kontrolę.
W wielu przypadkach możesz zezwolić na wykonanie tego z odpowiednim czasem, ale w niektórych przypadkach warto powiadomić użytkownika o oczekującej aktualizacji skryptu service worker, a następnie zautomatyzować proces przełączania się na nowy skrypt service worker. Aby to zrobić, dodaj kod na stronie i skrypt service worker.
Kod, który należy umieścić na stronie
Poniższy kod jest uruchamiany we wbudowanym elemencie <script>
za pomocą modułów JavaScript zaimportowanych z wersji workbox-window
hostowanej w sieci CDN. Rejestruje skrypt service worker za pomocą workbox-window
i reaguje, jeśli utknie na etapie oczekiwania. Po znalezieniu oczekującego skryptu service worker użytkownik jest informowany o dostępności zaktualizowanej wersji witryny oraz proponuje ponowne załadowanie strony.
<!-- This script tag uses JavaScript modules, so the proper `type` attribute value is required -->
<script type="module">
// This code sample uses features introduced in Workbox v6.
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
let registration;
const showSkipWaitingPrompt = async (event) => {
// Assuming the user accepted the update, set up a listener
// that will reload the page as soon as the previously waiting
// service worker has taken control.
wb.addEventListener('controlling', () => {
// At this point, reloading will ensure that the current
// tab is loaded under the control of the new service worker.
// Depending on your web app, you may want to auto-save or
// persist transient state before triggering the reload.
window.location.reload();
});
// When `event.wasWaitingBeforeRegister` is true, a previously
// updated service worker is still waiting.
// You may want to customize the UI prompt accordingly.
// This code assumes your app has a promptForUpdate() method,
// which returns true if the user wants to update.
// Implementing this is app-specific; some examples are:
// https://open-ui.org/components/alert.research or
// https://open-ui.org/components/toast.research
const updateAccepted = await promptForUpdate();
if (updateAccepted) {
wb.messageSkipWaiting();
}
};
// Add an event listener to detect when the registered
// service worker has installed but is waiting to activate.
wb.addEventListener('waiting', (event) => {
showSkipWaitingPrompt(event);
});
wb.register();
}
</script>
Jeśli je zaakceptuje, messageSkipWaiting()
nakazuje czekającemu skryptowi service worker wywołanie self.skipWaiting()
, co oznacza, że rozpocznie się aktywacja. Po aktywowaniu nowy skrypt service worker przejmie kontrolę nad wszystkimi istniejącymi klientami, aktywując zdarzenie controlling
w workbox-window
. W takim przypadku bieżąca strona załaduje się ponownie przy użyciu najnowszej wersji wszystkich zasobów wstępnie zapisanych w pamięci podręcznej oraz nowej logiki routingu wykrytej w zaktualizowanym mechanizmie Service Worker.
Kod, który należy umieścić w skrypcie service worker
Po otrzymaniu kodu z poprzedniej sekcji na stronie musisz dodać do skryptu service worker kod, który poinformuje go, kiedy pominąć fazę oczekiwania. Jeśli używasz generateSW
z workbox-build
i masz ustawioną opcję skipWaiting
na false
(domyślną), nie musisz nic robić, ponieważ poniższy kod zostanie automatycznie dołączony do wygenerowanego pliku skryptu service worker.
Jeśli tworzysz własny skrypt service worker – być może w połączeniu z jednym z narzędzi do kompilacji Workbox w trybie injectManifest
– musisz samodzielnie dodać ten kod:
addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
Spowoduje to nasłuchiwanie wiadomości wysyłanych z systemu workbox-window
do skryptu service worker o wartości type
o wartości SKIP_WAITING
, a gdy to nastąpi, wywołuje metodę self.skipWaiting()
. Za wysłanie tej wiadomości odpowiada metoda messageSkipWaiting()
w interfejsie workbox-window
, widoczna we wcześniejszym przykładowym kodzie.
Czy chcesz pokazać komunikat?
Nie jest to wzorzec, z którego musi korzystać każda aplikacja wdrażająca mechanizm Service Worker. Jest on używany w wybranych scenariuszach, w których brak możliwości ponownego załadowania strony po aktualizacji skryptu service worker może spowodować nieoczekiwane zachowania. Nie ma sztywnych i szybkich reguł, które określają, czy polecenie ponownego załadowania warto wyświetlić. Oto kilka sytuacji, w których takie polecenie może mieć sens:
- Intensywnie korzystasz z pamięci podręcznej. Jeśli chodzi o zasoby statyczne, później możesz mieć problemy, jeśli do obsługi żądań nawigacji będziesz wykorzystywać strategię ukierunkowaną na sieć lub sieć, ale leniwe ładowanie zasobów statycznych. Może to powodować sytuacje, w których zasoby z obsługą wersji mogą ulec zmianie, a skrypt service worker nie umieścił ich w pamięci podręcznej. Użycie przycisku ponownego załadowania pozwala uniknąć niektórych nieoczekiwanych zachowań.
- Jeśli używasz kodu HTML w pamięci podręcznej, W takim przypadku zdecydowanie zalecamy udostępnienie przycisku ponownego załadowania przy aktualizacjach skryptu service worker, ponieważ aktualizacje kodu HTML nie zostaną rozpoznane, dopóki zaktualizowany skrypt Service nie przejmie kontroli.
- Jeśli nie używasz zwykle buforowania w czasie działania. Podczas buforowania zasobów w czasie działania nie musisz informować użytkownika o konieczności ponownego załadowania. Zasoby z obsługą wersji będą w przyszłości dodawane do pamięci podręcznej środowiska wykonawczego, o ile w żądaniach nawigacyjnych jest stosowana strategia ukierunkowana na sieć lub tylko sieć.
- Jeśli używasz strategii stale podczas ponownej weryfikacji, możesz użyć modułu
workbox-broadcast-update
, aby powiadamiać użytkowników o aktualizacjach skryptu service worker.
To, czy musisz powiadamiać użytkownika o aktualizacjach skryptu service worker, zależy od Twojej aplikacji i jej unikalnych wymagań. Jeśli stwierdzisz, że po uruchomieniu nowego skryptu service worker użytkownicy zachowują się dziwnie, jest to najlepszy sygnał, że należy ich powiadomić.