Tworzenie elastycznych funkcji wyszukiwania za pomocą Workbox

Z tego ćwiczenia w Codelabs dowiesz się, jak wdrożyć odporne środowisko wyszukiwania za pomocą aplikacji Workbox. Używana przez nią aplikacja w wersji demonstracyjnej 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 udostępnić projekt do edycji, kliknij Remiksuj, aby edytować.
  • Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie naciśnij Pełny ekran pełny ekran

Na nowej karcie, która została właśnie otwarta, sprawdź, jak strona zachowuje się po przejściu do trybu offline:

  1. Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
  2. Kliknij kartę Sieć.
  3. Otwórz Narzędzia deweloperskie w Chrome i kliknij panel Sieć.
  4. Z listy Ograniczanie wybierz Offline.
  5. W aplikacji w wersji demonstracyjnej wpisz zapytanie, a następnie kliknij przycisk Szukaj.

Wyświetlana jest standardowa strona błędu przeglądarki:

Zrzut ekranu pokazujący domyślny interfejs offline w przeglądarce.

Podaj odpowiedź zastępczą

Skrypt service worker zawiera kod dodający stronę offline do listy precache, więc zawsze może być ona buforowana w zdarzeniu install skryptu service worker.

Zwykle konieczne jest poinstruowanie Workbox, aby podczas kompilacji dodał ten plik do listy wstępnego bufora, integrując bibliotekę z wybranym narzędziem do kompilacji (np. webpack lub gulp).

Dla uproszczenia zrobiliśmy to już za Ciebie. Robi to 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:

  1. Aby wyświetlić źródło, kliknij Wyświetl źródło.
  2. Dodaj ten kod na końcu 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:

  • Definiuje domyślną strategię Tylko sieć, która będzie stosowana do wszystkich żądań.
  • Deklaruje globalny moduł obsługi błędów, wywołując funkcję 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ę:

  1. Wróć na inną kartę, na której działa Twoja aplikacja.
  2. Na liście Throttling ustaw ponownie opcję Online.
  3. Aby wrócić na stronę wyszukiwania, naciśnij przycisk Wstecz w Chrome.
  4. Upewnij się, że pole wyboru Wyłącz pamięć podręczną w Narzędziach deweloperskich jest wyłączone.
  5. Przytrzymaj przycisk Załaduj ponownie w Chrome i wybierz Opróżnij pamięć podręczną i ponownie załaduj ponownie , aby upewnić się, że skrypt service worker został zaktualizowany.
  6. Ponownie wybierz na liście Ograniczanie opcję Offline.
  7. Wpisz zapytanie i ponownie kliknij przycisk Szukaj.

Zobaczysz zastępczą stronę HTML:

Zrzut ekranu niestandardowego interfejsu offline w przeglądarce.

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 umożliwiający wysyłanie próśb o zgodę na wyświetlanie powiadomień:

function requestNotificationPermission(event) {
  event.preventDefault();

  Notification.requestPermission().then(function (result) {
    showOfflineText(result);
  });
}

Kod wykonuje te czynności:

  • Gdy użytkownik kliknie Subskrybuj powiadomienia, wywoływana jest funkcja requestNotificationPermission(), która wywołuje funkcję Notification.requestPermission(), aby wyświetlić domyślną prośbę o przyznanie uprawnień przeglądarki. Obietnica rozwiązuje się, gdy użytkownik udzieli uprawnień granted, denied lub default.
  • Przekazuje rozstrzygnięte uprawnienie usłudze showOfflineText(), aby użytkownik mógł wyświetlać odpowiedni tekst.

Zachowuj zapytania offline i ponów próbę, gdy odzyskasz połączenie z internetem

Następnie zaimplementuj synchronizację w tle z Workspace, aby zachować zapytania offline i móc je ponowić, gdy przeglądarka wykryje, że połączenie zostało przywrócone.

  1. Otwórz plik public/sw.js do edycji.
  2. Dodaj ten 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}&notification=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 było spróbować je później. Te żądania zostaną zachowane w IndexedDB.
  • maxRetentionTime wskazuje czas, przez jaki żądanie może być ponawiane. W tym przypadku wybieramy 60 minut (po tym czasie jest usuwany).
  • Najważniejszą częścią tego kodu jest onSync. To wywołanie zwrotne będzie wywoływane po przywróceniu połączenia, tak aby żądania w kolejce były pobierane z sieci.
  • Odpowiedź sieciowa jest dodawana do pamięci podręcznej offline-search-responses z dołączonym parametrem zapytania &notification=true, dzięki czemu ten wpis pamięci podręcznej może zostać przechwycony, gdy użytkownik kliknie powiadomienie.

Aby zintegrować synchronizację w tle ze swoją usługą, zdefiniuj strategię NetworkOnly dla żądań wysyłanych do adresu URL wyszukiwania (/search_action) i przekaż wcześniej zdefiniowaną wartość bgSyncPlugin. Dodaj ten kod na końcu 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],
  }),
);

Dzięki temu aplikacja Workbox zawsze korzysta z sieci, a w przypadku niepowodzenia żądań używa logiki synchronizacji w tle.

Następnie dodaj poniższy kod na dole strony public/sw.js, aby zdefiniować strategię buforowania dla żą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 pozwalający 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

  1. Wróć na inną kartę, na której działa Twoja aplikacja.
  2. Na liście Throttling ustaw ponownie opcję Online.
  3. Aby wrócić na stronę wyszukiwania, naciśnij przycisk Wstecz w Chrome.
  4. Przytrzymaj przycisk Załaduj ponownie w Chrome i wybierz Opróżnij pamięć podręczną i ponownie załaduj ponownie , aby upewnić się, że skrypt service worker został zaktualizowany.
  5. Ponownie wybierz na liście Ograniczanie opcję Offline.
  6. Wpisz zapytanie i ponownie kliknij przycisk Szukaj.
  7. Kliknij Subskrybuj powiadomienia.
  8. Gdy Chrome zapyta, czy chcesz przyznać aplikacji uprawnienia do wysyłania powiadomień, kliknij Zezwól.
  9. Wpisz inne zapytanie i ponownie kliknij przycisk Szukaj.
  10. Ponownie ustaw na liście Ograniczanie opcję Online.

Po przywróceniu połączenia pojawi się powiadomienie:

Zrzut ekranu przedstawiający cały proces offline.

Podsumowanie

Workbox ma wiele wbudowanych funkcji, dzięki którym Twoje aplikacje PWA są bardziej odporne i angażujące. W ramach tego ćwiczenia w Codelabs omówiliśmy, jak wdrożyć interfejs Background Sync API przy użyciu abstrakcji Workbox, aby mieć pewność, że zapytania offline nie zostaną utracone i można je powtarzać po przywróceniu połączenia. Wersja demonstracyjna to prosta aplikacja do wyszukiwania, ale w bardziej złożonych scenariuszach i przypadkach użycia możesz zastosować podobną implementację, np. komunikator internetowy czy publikowanie wiadomości w sieciach społecznościowych.