Tworzenie elastycznych funkcji wyszukiwania za pomocą Workbox

Z tego ćwiczenia z kodem dowiesz się, jak wdrożyć wyszukiwarkę odporną na awarie za pomocą 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ść

Zanim dodasz optymalizacje, warto najpierw przeanalizować bieżący stan aplikacji.

  • Kliknij Remix to Edit (Zmiksuj do edycji), aby umożliwić edycję projektu.
  • Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie kliknij Pełny ekranpełny ekran.

W nowej karcie, która się otworzy, sprawdź, jak działa witryna w trybie offline:

  1. Aby otworzyć Narzędzia dla programistów, naciśnij `Control+Shift+J` (lub `Command+Option+J` na Macu).
  2. Kliknij kartę Sieć.
  3. Otwórz Narzędzia deweloperskie w Chrome i kliknij panel Sieć.
  4. Na liście 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ślną wygodę użytkownika w trybie offline w przeglądarce.

Podaj odpowiedź zastępczą

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:

  1. Aby wyświetlić źródło, kliknij Wyświetl źródło.
  2. 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() w celu zarządzania nieudanymi żądaniami. Gdy żądania dotyczą dokumentów, zwracana jest zapasowa strona HTML.

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 Disable cache (Wyłącz pamięć podręczną) w Narzędziach deweloperskich jest wyłączone.
  5. Przytrzymaj przycisk Odśwież w Chrome i wybierz Opróżnij pamięć podręczną i odśwież, aby zaktualizować usługę.
  6. Ponownie ustaw na liście Ograniczanie opcję Offline.
  7. Wpisz zapytanie i ponownie kliknij przycisk Szukaj.

Wyświetla się strona HTML awaryjnego:

Zrzut ekranu pokazujący niestandardową wersję trybu offline w przeglądarce.

Prośba o zgodę na wyświetlanie powiadomień

W celu uproszczenia 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 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 Workbox, aby zachować zapytania offline, dzięki czemu można je powtórzyć, gdy przeglądarka wykryje, że połączenie zostało przywrócone.

  1. Otwórz plik public/sw.js do edycji.
  2. 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}&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 je było później ponownie wykonać. Te żądania zostaną zachowane 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 odrzucony).
  • onSync jest najważniejszą częścią tego kodu. Ten wywołanie zwrotne zostanie wywołany, gdy połączenie zostanie przywrócone, aby pobrane z sieci żądania znalazły się w kolejce.
  • Odpowiedź sieci jest dodawana do pamięci podręcznej offline-search-responses z dodaniem parametru zapytania &notification=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 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],
  }),
);

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 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 w Chrome przycisk Wstecz.
  4. Przytrzymaj przycisk Odśwież w Chrome i wybierz Opróżnij pamięć podręczną i odśwież, aby zaktualizować usługę.
  5. Ponownie ustaw 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 kolejne zapytanie i ponownie kliknij przycisk Szukaj.
  10. Z listy Ograniczanie ponownie wybierz pozycję Online.

Gdy połączenie zostanie przywrócone, pojawi się powiadomienie:

Zrzut ekranu przedstawiający pełny proces offline.

Podsumowanie

Workbox ma wiele wbudowanych funkcji, dzięki którym Twoje aplikacje PWA są bardziej odporne i angażujące. 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 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.