Stabile Suchfunktionen mit Workbox

In diesem Codelab erfahren Sie, wie Sie mit Workbox eine zuverlässige Suche implementieren. Die verwendete Demo-App enthält ein Suchfeld, das einen Serverendpunkt aufruft und den Nutzer zu einer einfachen HTML-Seite weiterleitet.

Messen

Bevor Sie Optimierungen vornehmen, sollten Sie immer zuerst den aktuellen Zustand der Anwendung analysieren.

  • Klicke auf Remix zum Bearbeiten, um das Projekt bearbeitbar zu machen.
  • Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild Vollbild.

Sehen Sie sich in dem gerade geöffneten Tab an, wie sich die Website verhält, wenn Sie offline gehen:

  1. Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Optionstaste + J“ auf einem Mac), um die Entwicklertools zu öffnen.
  2. Klicken Sie auf den Tab Netzwerk.
  3. Öffnen Sie die Chrome-Entwicklertools und wählen Sie den Bereich „Netzwerk“ aus.
  4. Wählen Sie in der Drop-down-Liste Drosselung die Option Offline aus.
  5. Geben Sie in der Demo-App eine Suchanfrage ein und klicken Sie auf die Schaltfläche Suchen.

Die Standard-Browserfehlerseite wird angezeigt:

Ein Screenshot der standardmäßigen Offline-UX im Browser.

Fallback-Antwort bereitstellen

Der Dienst-Worker enthält den Code, mit dem die Offlineseite der Liste für den Pre-Cache hinzugefügt wird, damit sie immer beim Dienst-Worker-Ereignis install im Cache gespeichert werden kann.

Normalerweise müssen Sie Workbox anweisen, diese Datei zur Pre-Cache-Liste hinzuzufügen, indem Sie die Bibliothek in Ihr bevorzugtes Build-Tool einbinden (z.B. webpack oder gulp).

Der Einfachheit halber haben wir das bereits für Sie erledigt. Das geschieht mit dem folgenden Code bei public/sw.js:

const FALLBACK_HTML_URL = '/index_offline.html';
…
workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

Fügen Sie als Nächstes Code hinzu, um die Offlineseite als Fallback-Antwort zu verwenden:

  1. Wenn Sie die Quelle aufrufen möchten, drücken Sie Quellcode ansehen.
  2. Fügen Sie den folgenden Code am Ende von public/sw.js ein:
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();
  }
});

Der Code führt Folgendes aus:

  • Hiermit wird eine Standardstrategie vom Typ Nur Netzwerk definiert, die auf alle Anfragen angewendet wird.
  • Deklariert einen globalen Fehlerhandler, indem workbox.routing.setCatchHandler() aufgerufen wird, um fehlgeschlagene Anfragen zu verwalten. Bei Anfragen für Dokumente wird eine Fallback-Offline-HTML-Seite zurückgegeben.

So testen Sie diese Funktion:

  1. Kehren Sie zum anderen Tab zurück, auf dem Ihre App ausgeführt wird.
  2. Stellen Sie in der Drop-down-Liste Drosselung wieder Online ein.
  3. Drücken Sie die Schaltfläche Zurück in Chrome, um zur Suchseite zurückzukehren.
  4. Das Kästchen Cache deaktivieren in den Entwicklertools muss deaktiviert sein.
  5. Halten Sie die Schaltfläche Aktualisieren in Chrome gedrückt und wählen Sie Cache leeren und hart neu laden aus, um sicherzustellen, dass Ihr Service Worker aktualisiert wird.
  6. Stellen Sie in der Drop-down-Liste Throttling (Drosselung) wieder Offline ein.
  7. Geben Sie eine Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.

Die Fallback-HTML-Seite wird angezeigt:

Ein Screenshot der benutzerdefinierten Offline-UX im Browser.

Berechtigung zum Senden von Benachrichtigungen anfordern

Der Code zum Anfordern von Berechtigungen für Benachrichtigungen ist bereits in der Offlineseite unter views/index_offline.html in einem Scriptblock unten enthalten:

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

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

Der Code führt Folgendes aus:

  • Wenn der Nutzer auf Benachrichtigungen abonnieren klickt, wird die Funktion requestNotificationPermission() aufgerufen, die wiederum Notification.requestPermission() aufruft, um die Standardaufforderung zur Browserberechtigung anzuzeigen. Das Versprechen wird mit der vom Nutzer ausgewählten Berechtigung aufgelöst. Das kann entweder granted, denied oder default sein.
  • Übergibt die ermittelte Berechtigung an showOfflineText(), um dem Nutzer den entsprechenden Text anzuzeigen.

Offlineabfragen beibehalten und noch einmal versuchen, wenn Sie wieder online sind

Implementieren Sie als Nächstes die Workbox-Hintergrundsynchronisierung, um Offlineabfragen zu speichern, damit sie wiederholt werden können, wenn der Browser erkennt, dass die Verbindung wiederhergestellt wurde.

  1. Öffnen Sie public/sw.js zum Bearbeiten.
  2. Fügen Sie am Ende der Datei den folgenden Code ein:
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;
      }
    }
  },
});

Der Code führt Folgendes aus:

  • workbox.backgroundSync.Plugin enthält die Logik, mit der fehlgeschlagene Anfragen einer Warteschlange hinzugefügt werden, damit sie später noch einmal versucht werden können. Diese Anfragen werden in IndexedDB gespeichert.
  • maxRetentionTime gibt an, wie lange eine Anfrage wiederholt werden kann. In diesem Fall haben wir 60 Minuten ausgewählt (nach denen die Daten verworfen werden).
  • onSync ist der wichtigste Teil dieses Codes. Dieser Rückruf wird aufgerufen, wenn die Verbindung wiederhergestellt wurde, damit die anstehenden Anfragen abgerufen und dann aus dem Netzwerk abgerufen werden.
  • Die Netzwerkantwort wird dem offline-search-responses-Cache hinzugefügt und die Abfrageparameter &notification=true werden angehängt, damit dieser Cacheeintrag abgerufen werden kann, wenn ein Nutzer auf die Benachrichtigung klickt.

Wenn Sie die Hintergrundsynchronisierung in Ihren Dienst einbinden möchten, definieren Sie eine NetworkOnly-Strategie für Anfragen an die Such-URL (/search_action) und übergeben Sie die zuvor definierte bgSyncPlugin. Fügen Sie den folgenden Code am Ende von public/sw.js ein:

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],
  }),
);

Dadurch wird Workbox angewiesen, immer das Netzwerk aufzurufen und bei fehlgeschlagenen Anfragen die Hintergrundsynchronisierungslogik zu verwenden.

Fügen Sie als Nächstes unten in public/sw.js den folgenden Code hinzu, um eine Caching-Strategie für Anfragen zu definieren, die von Benachrichtigungen stammen. Verwenden Sie die Strategie CacheFirst, damit sie aus dem Cache bereitgestellt werden können.

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',
  })
);

Fügen Sie abschließend den Code hinzu, um Benachrichtigungen anzuzeigen:

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)
  );
});

Funktion testen

  1. Kehren Sie zum anderen Tab zurück, auf dem Ihre App ausgeführt wird.
  2. Stellen Sie in der Drop-down-Liste Drosselung wieder Online ein.
  3. Drücken Sie die Schaltfläche Zurück in Chrome, um zur Suchseite zurückzukehren.
  4. Halten Sie die Schaltfläche Aktualisieren in Chrome gedrückt und wählen Sie Cache leeren und hart neu laden aus, um sicherzustellen, dass Ihr Service Worker aktualisiert wird.
  5. Stellen Sie in der Drop-down-Liste Throttling (Drosselung) wieder Offline ein.
  6. Geben Sie eine Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.
  7. Klicke auf Benachrichtigungen abonnieren.
  8. Wenn Sie in Chrome gefragt werden, ob Sie der App die Berechtigung zum Senden von Benachrichtigungen erteilen möchten, klicken Sie auf Zulassen.
  9. Geben Sie eine weitere Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.
  10. Stellen Sie in der Drop-down-Liste Throttling (Drosselung) wieder Online ein.

Sobald die Verbindung wiederhergestellt ist, wird eine Benachrichtigung angezeigt:

Screenshot des gesamten Ablaufs im Offlinemodus

Fazit

Workbox bietet viele integrierte Funktionen, mit denen Sie Ihre PWAs robuster und ansprechender gestalten können. In diesem Codelab haben Sie gelernt, wie Sie die Background Sync API über die Workbox-Abstraktion implementieren, damit Offlineabfragen von Nutzern nicht verloren gehen und nach Wiederherstellung der Verbindung noch einmal versucht werden können. Die Demo ist eine einfache Such-App, aber Sie können eine ähnliche Implementierung auch für komplexere Szenarien und Anwendungsfälle verwenden, z. B. für Chat-Apps oder das Posten von Nachrichten in einem sozialen Netzwerk.