Tworzenie elastycznych funkcji wyszukiwania za pomocą Workbox

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 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:

  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 wybierz panel Network.
  4. Z listy Ograniczanie wybierz Offline.
  5. W wersji demonstracyjnej wpisz zapytanie, a potem kliknij przycisk Szukaj.

Wyświetla się 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 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:

  1. Aby wyświetlić źródło, kliknij Wyświetl źródło.
  2. 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ę:

  1. Wróć na inną kartę, na której działa Twoja aplikacja.
  2. Z powrotem na liście Throttling wybierz Online.
  3. Aby wrócić do strony 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. 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.
  6. Ponownie w menu Ograniczanie ustaw Offline.
  7. Wpisz zapytanie i ponownie kliknij przycisk Wyszukaj.

Wyświetli się zastępcza strona HTML:

Zrzut ekranu przedstawiający niestandardowy interfejs 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 żą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 lub default.
  • 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.

  1. Otwórz public/sw.js, by edytować.
  2. 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}&notification=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 &notification=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

  1. Wróć na inną kartę, na której działa Twoja aplikacja.
  2. Z powrotem na liście Throttling wybierz Online.
  3. Aby wrócić do strony wyszukiwania, naciśnij przycisk Wstecz w Chrome.
  4. 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.
  5. Ponownie w menu Ograniczanie ustaw Offline.
  6. Wpisz zapytanie i ponownie kliknij przycisk Wyszukaj.
  7. Kliknij Zasubskrybuj powiadomienia.
  8. Gdy Chrome zapyta, czy chcesz udzielić aplikacji uprawnień do wysyłania powiadomień, kliknij Zezwól.
  9. Wpisz inne zapytanie i jeszcze raz kliknij przycisk Szukaj.
  10. Z powrotem w menu Throttling wybierz Online.

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

Zrzut ekranu całego procesu offline.

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.