Z tego ćwiczenia z kodem dowiesz się, jak wdrożyć wyszukiwarkę odporną na awarie za pomocą Workbox. Aplikacja demonstracyjna zawiera pole wyszukiwania, które wywołuje punkt końcowy na serwerze i przekierowuje użytkownika do podstawowej strony HTML.
Zmierz odległość
Zanim dodasz optymalizacje, warto najpierw przeanalizować bieżący stan aplikacji.
- Kliknij Remixuj do edycji, aby umożliwić edycję projektu.
- Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie kliknij Pełny ekran .
W nowej karcie, która się otworzy, sprawdź, jak działa witryna w trybie offline:
- Aby otworzyć Narzędzia dla programistów, naciśnij `Control+Shift+J` (lub `Command+Option+J` na Macu).
- Kliknij kartę Sieć.
- Otwórz Narzędzia deweloperskie w Chrome i wybierz panel Sieć.
- Na liście Ograniczanie wybierz Offline.
- W aplikacji demonstracyjnej wpisz zapytanie, a potem kliknij przycisk Szukaj.
Wyświetla się standardowa strona błędu przeglądarki:
Podanie odpowiedzi zastępczej
Usługa wtyczki zawiera kod, który dodaje stronę offline do listy wcześniejszego buforowania, dzięki czemu może ona zawsze być buforowana w ramach zdarzenia install
usługi wtyczki.
Zwykle musisz poprosić Workbox, aby dodał ten plik do listy wstępnego buforowania w momencie kompilacji, integrując bibliotekę z wybranym narzędziem do kompilacji (np. webpack lub gulp).
W celu uproszczenia tego procesu zrobiliśmy to już za Ciebie. Ten kod w pliku public/sw.js
wykonuje te czynności:
const FALLBACK_HTML_URL = '/index_offline.html';
…
workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);
Następnie dodaj kod, który użyje strony offline jako odpowiedzi zapasowej:
- Aby wyświetlić źródło, naciśnij Wyświetl źródło.
- Dodaj ten kod na dole pliku
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();
}
});
Kod wykonuje te czynności:
- Określa domyślną strategię tylko w sieci, która będzie stosowana do wszystkich żądań.
- Deklaruje globalny moduł obsługi błędów, wywołując funkcję
workbox.routing.setCatchHandler()
do zarządzania nieudanymi żądaniami. Gdy żądania dotyczą dokumentów, zwracana jest strona HTML offline.
Aby przetestować tę funkcję:
- Wróć do innej karty, na której uruchomiona jest aplikacja.
- Z listy Ograniczanie wybierz ponownie pozycję Online.
- Aby wrócić na stronę wyszukiwania, naciśnij w Chrome przycisk Wstecz.
- Upewnij się, że pole wyboru Disable cache (Wyłącz pamięć podręczną) w Narzędziach deweloperskich jest wyłączone.
- Naciśnij i przytrzymaj przycisk Odśwież w Chrome, a następnie wybierz Opróżnij pamięć podręczną i odśwież, aby zaktualizować usługę.
- Z listy Ograniczanie ponownie wybierz pozycję W trybie offline.
- Wpisz zapytanie i ponownie kliknij przycisk Szukaj.
Wyświetla się strona HTML awaryjnego:
Prośba o zgodę na wyświetlanie powiadomień
Dla ułatwienia strona offline na stronie views/index_offline.html
zawiera już kod do żądania uprawnień do powiadomień w bloku skryptu na dole:
function requestNotificationPermission(event) {
event.preventDefault();
Notification.requestPermission().then(function (result) {
showOfflineText(result);
});
}
Kod wykonuje te czynności:
- Gdy użytkownik kliknie Zasubskrybuj powiadomienia, wywoływana jest funkcja
requestNotificationPermission()
, która wywołuje funkcjęNotification.requestPermission()
, aby wyświetlić domyślny komunikat z prośbą o uprawnienia w przeglądarce. Obietnica jest realizowana zgodnie z uprawnieniami wybranymi przez użytkownika, które mogą byćgranted
,denied
lubdefault
. - Przekazuje rozwiązane uprawnienie do
showOfflineText()
, aby wyświetlić odpowiedni tekst użytkownikowi.
Zapisywanie zapytań offline i próba ponownego wykonania po przywróceniu połączenia z internetem
Następnie zaimplementuj synchronizację w tle Workbox, aby zachować zapytania offline, dzięki czemu można je powtórzyć, gdy przeglądarka wykryje, że połączenie zostało przywrócone.
- Otwórz plik
public/sw.js
do edycji. - Dodaj na końcu pliku ten kod:
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;
}
}
},
});
Kod wykonuje te czynności:
workbox.backgroundSync.Plugin
zawiera logikę dodawania nieudanych żądań do kolejki, aby można je było później ponownie wykonać. Te żądania są przechowywane w IndexedDB.maxRetentionTime
wskazuje czas, przez jaki można powtórzyć próbę wykonania żądania. W tym przypadku wybrano 60 minut (po tym czasie plik zostanie usunięty).onSync
jest najważniejszą częścią tego kodu. To wywołanie zwrotne zostanie wywołane po przywróceniu połączenia, aby pobrane z sieci żądania z kolejki mogły zostać pobrane.- Odpowiedź sieci jest dodawana do pamięci podręcznej
offline-search-responses
z dodaniem parametru zapytania¬ification=true
, aby można było ją pobrać, gdy użytkownik kliknie powiadomienie.
Aby zintegrować synchronizację w tle z usługą, zdefiniuj strategię NetworkOnly dla żądań do adresu URL wyszukiwarki (/search_action
) i prześlij zdefiniowaną wcześniej wartość bgSyncPlugin
. Dodaj ten kod na dole pliku 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],
}),
);
To polecenie informuje Workbox, aby zawsze łączył się z siecią, a w przypadku niepowodzenia żądania używał logiki synchronizacji w tle.
Następnie dodaj ten kod na dole pliku public/sw.js
, aby zdefiniować strategię buforowania dla żądań pochodzących z powiadomień. Użyj strategii CacheFirst, aby mogły być dostarczane 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, aby wyświetlać powiadomienia:
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 funkcji
- Wróć do innej karty, na której uruchomiona jest aplikacja.
- Z listy Ograniczanie wybierz ponownie pozycję Online.
- Aby wrócić na stronę wyszukiwania, naciśnij w Chrome przycisk Wstecz.
- Naciśnij i przytrzymaj przycisk Odśwież w Chrome, a następnie wybierz Opróżnij pamięć podręczną i odśwież, aby zaktualizować usługę.
- Z listy Ograniczanie wybierz ponownie pozycję W trybie offline.
- Wpisz zapytanie i ponownie kliknij przycisk Szukaj.
- Kliknij Subskrybuj powiadomienia.
- Gdy Chrome zapyta, czy chcesz zezwolić aplikacji na wysyłanie powiadomień, kliknij Zezwól.
- Wpisz kolejne zapytanie i ponownie kliknij przycisk Szukaj.
- Z listy Ograniczanie ponownie wybierz pozycję Online.
Gdy połączenie zostanie przywrócone, pojawi się powiadomienie:
Podsumowanie
Workbox udostępnia wiele wbudowanych funkcji, które sprawiają, że PWA są bardziej odporne i zaangażowane. W tym laboratorium kodu poznasz sposób implementacji interfejsu Background Sync API za pomocą abstrakcji Workbox, aby zapewnić, że zapytania użytkowników offline nie zostaną utracone i można będzie je powtórzyć, gdy połączenie zostanie przywrócone. Demonstracja to prosta aplikacja do wyszukiwania, ale możesz użyć podobnej implementacji w bardziej złożonych scenariuszach i przypadkach użycia, np. w aplikacjach do czatu czy przy publikowaniu wiadomości w sieci społecznościowej.