Z tego ćwiczenia w programie dowiesz się, jak wdrożyć odporne środowisko wyszukiwania w Workbox. Używana w wersji demonstracyjnej aplikacja zawiera pole wyszukiwania, które wywołuje punkt końcowy serwera i przekierowuje użytkownika na podstawową stronę HTML.
Zmierz odległość
Przed dodaniem optymalizacji zawsze warto najpierw przeanalizować bieżący stan aplikacji.
- Aby umożliwić edytowanie projektu, kliknij Zremiksuj do edycji.
- Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a potem Pełny ekran .
Na nowej karcie, która się właśnie otworzyła, sprawdź, jak strona zachowuje się po przejściu do trybu offline:
- Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
- Kliknij kartę Sieć.
- Otwórz Narzędzia deweloperskie w Chrome i wybierz panel Network.
- Z listy Ograniczanie wybierz Offline.
- W wersji demonstracyjnej wpisz zapytanie, a potem kliknij przycisk Szukaj.
Wyświetla się standardowa strona błędu przeglądarki:
Podaj odpowiedź zastępczą
Skrypt service worker zawiera kod powodujący dodanie strony offline do listy precache, która musi być przechowywana w pamięci podręcznej przez zdarzenie install
skryptu service worker.
Zwykle musisz nakazać Workbox dodanie tego pliku do listy precache na czas kompilacji, integrując bibliotekę z wybranym narzędziem do kompilacji (np. webpack lub gulp).
Dla Twojej wygody zrobiliśmy to już za Ciebie. Służy do tego następujący kod na stronie public/sw.js
:
const FALLBACK_HTML_URL = '/index_offline.html';
…
workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);
Następnie dodaj kod, który będzie używać strony offline jako odpowiedzi zastępczej:
- Aby wyświetlić źródło, kliknij Wyświetl źródło.
- Dodaj ten kod na końcu strony
public/sw.js
:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());
workbox.routing.setCatchHandler(({event}) => {
switch (event.request.destination) {
case 'document':
return caches.match(FALLBACK_HTML_URL);
break;
default:
return Response.error();
}
});
Ten kod wykonuje te operacje:
- Określa domyślną strategię dotyczącą tylko sieci, która będzie stosowana do wszystkich żądań.
- Deklaruje globalny moduł obsługi błędów, wywołując
workbox.routing.setCatchHandler()
w celu zarządzania nieudanymi żądaniami. Gdy żądania dotyczą dokumentów, zwracana jest zastępcza strona HTML offline.
Aby przetestować tę funkcję:
- Wróć na inną kartę, na której działa Twoja aplikacja.
- Z powrotem na liście Throttling wybierz Online.
- Aby wrócić do strony wyszukiwania, naciśnij przycisk Wstecz w Chrome.
- Upewnij się, że pole wyboru Wyłącz pamięć podręczną w Narzędziach deweloperskich jest wyłączone.
- Naciśnij i przytrzymaj przycisk Załaduj ponownie w Chrome i wybierz Opróżnij pamięć podręczną i wytrwale załaduj ponownie, aby upewnić się, że skrypt service worker został zaktualizowany.
- Ponownie w menu Ograniczanie ustaw Offline.
- Wpisz zapytanie i ponownie kliknij przycisk Wyszukaj.
Wyświetli się zastępcza strona HTML:
Poproś o zgodę na wyświetlanie powiadomień
Dla uproszczenia strona offline pod adresem views/index_offline.html
zawiera już w bloku skryptu u dołu kod żądania pozwolenia na wyświetlanie powiadomień:
function requestNotificationPermission(event) {
event.preventDefault();
Notification.requestPermission().then(function (result) {
showOfflineText(result);
});
}
Ten kod wykonuje te operacje:
- Gdy użytkownik kliknie Subskrybuj powiadomienia, wywoływana jest funkcja
requestNotificationPermission()
, która wywołuje funkcjęNotification.requestPermission()
, aby wyświetlić domyślny monit o przyznanie uprawnień przeglądarki. Obietnica ustępuje wraz z uprawnieniem wybranym przez użytkownika. Mogą to byćgranted
,denied
lubdefault
. - Przekazuje uznane uprawnienie do
showOfflineText()
, aby wyświetlić użytkownikowi odpowiedni tekst.
Zachowuj zapytania offline i spróbuj ponownie, gdy odzyskasz połączenie z internetem
Następnie zaimplementuj synchronizację obszaru roboczego, aby zachować zapytania offline i móc je ponowić, gdy przeglądarka wykryje, że łączność została zwrócona.
- Otwórz
public/sw.js
, by edytować. - Dodaj następujący kod na końcu pliku:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
maxRetentionTime: 60,
onSync: async ({queue}) => {
let entry;
while ((entry = await queue.shiftRequest())) {
try {
const response = await fetch(entry.request);
const cache = await caches.open('offline-search-responses');
const offlineUrl = `${entry.request.url}¬ification=true`;
cache.put(offlineUrl, response);
showNotification(offlineUrl);
} catch (error) {
await this.unshiftRequest(entry);
throw error;
}
}
},
});
Ten kod wykonuje te operacje:
workbox.backgroundSync.Plugin
zawiera logikę dodawania nieudanych żądań do kolejki, aby można je było później ponowić. Żądania te zostaną zachowane w IndexedDB.maxRetentionTime
wskazuje, ile czasu można ponowić żądanie. W tym przypadku wybraliśmy 60 minut (po tym czasie zostanie ona odrzucona).- Elementem
onSync
jest najważniejsza część kodu. To wywołanie zwrotne zostanie wykonane po przywróceniu połączenia, tak aby żądania z kolejki zostały pobrane z sieci. - Odpowiedź sieciowa jest dodawana do pamięci podręcznej przeglądarki
offline-search-responses
z parametrem zapytania¬ification=true
, dzięki czemu ten wpis w pamięci podręcznej może zostać przechwycony, gdy użytkownik kliknie powiadomienie.
Aby zintegrować synchronizację w tle z usługą, zdefiniuj strategię NetworkOnly dla żądań wysyłanych na adres URL wyszukiwania (/search_action
) i przekaż wcześniej zdefiniowany parametr bgSyncPlugin
. Dodaj ten kod na końcu strony public/sw.js
:
const matchSearchUrl = ({url}) => {
const notificationParam = url.searchParams.get('notification');
return url.pathname === '/search_action' && !(notificationParam === 'true');
};
workbox.routing.registerRoute(
matchSearchUrl,
new workbox.strategies.NetworkOnly({
plugins: [bgSyncPlugin],
}),
);
Sprawi to, że Workbox zawsze korzysta z sieci, a w przypadku niepowodzenia używa logiki synchronizacji w tle.
Następnie dodaj poniższy kod na dole elementu public/sw.js
, aby zdefiniować strategię buforowania żądań pochodzących z powiadomień. Użyj strategii CacheFirst, aby mogły być wyświetlane z pamięci podręcznej.
const matchNotificationUrl = ({url}) => {
const notificationParam = url.searchParams.get('notification');
return (url.pathname === '/search_action' && (notificationParam === 'true'));
};
workbox.routing.registerRoute(matchNotificationUrl,
new workbox.strategies.CacheFirst({
cacheName: 'offline-search-responses',
})
);
Na koniec dodaj kod wyświetlania powiadomień:
function showNotification(notificationUrl) {
if (Notification.permission) {
self.registration.showNotification('Your search is ready!', {
body: 'Click to see you search result',
icon: '/img/workbox.jpg',
data: {
url: notificationUrl
}
});
}
}
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
Testowanie tej funkcji
- Wróć na inną kartę, na której działa Twoja aplikacja.
- Z powrotem na liście Throttling wybierz Online.
- Aby wrócić do strony wyszukiwania, naciśnij przycisk Wstecz w Chrome.
- Naciśnij i przytrzymaj przycisk Załaduj ponownie w Chrome i wybierz Opróżnij pamięć podręczną i wytrwale załaduj ponownie, aby upewnić się, że skrypt service worker został zaktualizowany.
- Ponownie w menu Ograniczanie ustaw Offline.
- Wpisz zapytanie i ponownie kliknij przycisk Wyszukaj.
- Kliknij Zasubskrybuj powiadomienia.
- Gdy Chrome zapyta, czy chcesz udzielić aplikacji uprawnień do wysyłania powiadomień, kliknij Zezwól.
- Wpisz inne zapytanie i jeszcze raz kliknij przycisk Szukaj.
- Z powrotem w menu Throttling wybierz Online.
Po przywróceniu połączenia pojawi się powiadomienie:
Podsumowanie
Workbox ma wiele wbudowanych funkcji, które zwiększają odporność i atrakcyjność Twoich aplikacji PWA. Dzięki temu ćwiczeniu w programie dowiesz się, jak wdrożyć interfejs Background Sync API za pomocą abstrakcji Workbox, aby nie utracić zapytań użytkowników offline i można je wykonać ponownie po przywróceniu połączenia. Wersja demonstracyjna jest prostą aplikacją do wyszukiwania, ale podobnego rozwiązania możesz używać w bardziej złożonych scenariuszach i przypadkach użycia – takich jak aplikacje do obsługi czatu czy publikowanie wiadomości w sieciach społecznościowych.