Stabile Suchfunktionen mit Workbox

Demián Renzulli
Demián Renzulli

In diesem Codelab erfahren Sie, wie Sie mit Workbox eine robuste Suchfunktion 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 hinzufügen, sollten Sie immer zuerst den aktuellen Zustand der Anwendung analysieren.

  • Klicken Sie auf Remix to Edit (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.

Prüfen Sie im gerade geöffneten neuen Tab, wie sich die Website verhält, wenn die Verbindung getrennt wird:

  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 das Netzwerk-Steuerfeld aus.
  4. Wählen Sie in der Drop-down-Liste für die Drosselung die Option Offline aus.
  5. Geben Sie in der Demo-App eine Suchanfrage ein und klicken Sie auf die Schaltfläche Suchen.

Die Standardfehlerseite des Browsers wird angezeigt:

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

Fallback-Antwort bereitstellen

Der Service Worker enthält den Code, mit dem die Offline-Seite der Precache-Liste hinzugefügt wird. Sie kann also immer beim install-Ereignis des Service Workers im Cache gespeichert werden.

Normalerweise müssen Sie Workbox anweisen, diese Datei während der Build-Phase der Precache-Liste hinzuzufügen. Dazu müssen Sie die Bibliothek in Ihr bevorzugtes Build-Tool (z. B. webpack oder gulp) einbinden.

Der Einfachheit halber haben wir das bereits für Sie erledigt. Der folgende Code in public/sw.js führt diese Aufgabe aus:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

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

  1. Wenn Sie die Quelle aufrufen möchten, drücken Sie Quelle 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:

  • Definiert eine Standardstrategie vom Typ Nur Netzwerk, die auf alle Anfragen angewendet wird.
  • Deklariert einen globalen Fehler-Handler, indem workbox.routing.setCatchHandler() aufgerufen wird, um fehlgeschlagene Anfragen zu verarbeiten. Bei Anfragen für Dokumente wird eine Offline-HTML-Seite als Fallback 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 die Drop-down-Liste Drosselung wieder auf Online ein.
  3. Klicken Sie in Chrome auf die Schaltfläche Zurück, um zur Suchseite zurückzukehren.
  4. Achten Sie darauf, dass das Kästchen Cache deaktivieren in den Entwicklertools deaktiviert ist.
  5. Halten Sie die Schaltfläche Neu laden 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 die Drop-down-Liste Drosselung wieder auf Offline ein.
  7. Geben Sie eine Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.

Die Fallback-HTML-Seite wird angezeigt:

Screenshot der benutzerdefinierten Offline-UX im Browser.

Berechtigung zum Senden von Benachrichtigungen anfordern

Der Einfachheit halber enthält die Offline-Seite unter views/index_offline.html bereits den Code zum Anfordern von Benachrichtigungsberechtigungen in einem Scriptblock unten:

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 Notification.requestPermission() aufruft, um die Standardaufforderung für Browserberechtigungen anzuzeigen. Das Promise wird mit der vom Nutzer ausgewählten Berechtigung aufgelöst, die entweder granted, denied oder default sein kann.
  • Übergibt die aufgelöste Berechtigung an showOfflineText(), um dem Nutzer den entsprechenden Text anzuzeigen.

Offline-Anfragen beibehalten und wiederholen, wenn wieder eine Verbindung besteht

Implementieren Sie als Nächstes Workbox Background Sync, um Offline-Anfragen beizubehalten, 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 zum Hinzufügen fehlgeschlagener Anfragen zu einer Warteschlange, damit sie später noch einmal versucht werden können. Diese Anfragen werden in IndexedDB gespeichert.
  • maxRetentionTime gibt an, wie oft eine Anfrage wiederholt werden darf. In diesem Fall haben wir 60 Minuten ausgewählt. Danach wird die Anfrage verworfen.
  • onSync ist der wichtigste Teil dieses Codes. Dieser Callback wird aufgerufen, wenn die Verbindung wiederhergestellt ist, damit in die Warteschlange gestellte Anfragen abgerufen und dann aus dem Netzwerk abgerufen werden.
  • Die Netzwerkantwort wird dem offline-search-responses-Cache hinzugefügt und der &notification=true-Suchparameter 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 auf das Netzwerk zuzugreifen und bei fehlgeschlagenen Anfragen die Logik für die Hintergrundsynchronisierung zu verwenden.

Fügen Sie als Nächstes den folgenden Code unten in public/sw.js ein, um eine Caching-Strategie für Anfragen aus Benachrichtigungen zu definieren. 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 zum Schluss den Code zum Anzeigen von Benachrichtigungen hinzu:

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 die Drop-down-Liste Drosselung wieder auf Online ein.
  3. Klicken Sie in Chrome auf die Schaltfläche Zurück, um zur Suchseite zurückzukehren.
  4. Halten Sie die Schaltfläche Neu laden 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 die Drop-down-Liste Drosselung wieder auf Offline ein.
  6. Geben Sie eine Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.
  7. Klicken Sie 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 andere Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.
  10. Stellen Sie die Drop-down-Liste Drosselung wieder auf Online ein.

Sobald die Verbindung wiederhergestellt ist, wird eine Benachrichtigung angezeigt:

Ein Screenshot des vollständigen Offlineworkflows.

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 Offline-Nutzeranfragen nicht verloren gehen und wiederholt werden können, sobald die Verbindung wiederhergestellt ist. Die Demo ist eine einfache Such-App, aber Sie können eine ähnliche Implementierung für komplexere Szenarien und Anwendungsfälle verwenden, z. B. für Chat-Apps oder zum Posten von Nachrichten in einem sozialen Netzwerk.