Stabile Suchfunktionen mit Workbox

In diesem Codelab erfahren Sie, wie Sie mit Workbox eine stabile Suchfunktion implementieren. Die verwendete Demo-App enthält ein Suchfeld, das einen Server-Endpunkt aufruft und den Nutzer auf eine einfache HTML-Seite weiterleitet.

Messen

Bevor Sie Optimierungen hinzufügen, sollten Sie immer zuerst den aktuellen Status der Anwendung analysieren.

  • Klicke auf Zu bearbeitende Remixe, damit das Projekt bearbeitet werden kann.
  • Um die Website als Vorschau anzusehen, wählen Sie App ansehen und dann Vollbild Vollbild aus.

Prüfen Sie auf dem neuen Tab, der gerade geöffnet wurde, wie sich die Website im Offlinemodus verhält:

  1. Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.
  2. Klicken Sie auf den Tab Netzwerk.
  3. Öffne die Chrome-Entwicklertools und wähle das Steuerfeld „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 dann auf die Schaltfläche Suchen.

Die Standard-Browserfehlerseite wird angezeigt:

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

Fallback-Antwort bereitstellen

Der Service Worker enthält den Code zum Hinzufügen der Offlineseite zur Precache-Liste, sodass sie immer beim Service Worker-Ereignis install im Cache gespeichert werden kann.

Normalerweise müssen Sie Workbox anweisen, diese Datei beim Build zur Precache-Liste hinzuzufügen, indem Sie die Bibliothek in das Build-Tool Ihrer Wahl einbinden, z.B. webpack oder gulp.

Der Einfachheit halber haben wir das bereits für Sie getan. Dazu kommt der folgende Code unter 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. Um die Quelle aufzurufen, drücken Sie Quelle anzeigen.
  2. Fügen Sie am Ende von public/sw.js den folgenden Code hinzu:
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 des Typs Nur Netzwerk, die für alle Anfragen gilt.
  • Deklariert einen globalen Fehler-Handler, 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 Funktionalität:

  1. Wechseln Sie zurück zum anderen Tab, auf dem Ihre App ausgeführt wird.
  2. Setzen Sie die Drop-down-Liste Drosselung wieder auf Online.
  3. Drücken Sie in Chrome die Schaltfläche Zurück, um zur Suchseite zurückzukehren.
  4. Achten Sie darauf, dass in den Entwicklertools das Kästchen Cache deaktivieren deaktiviert ist.
  5. Halten Sie die Schaltfläche Aktualisieren in Chrome lange gedrückt und wählen Sie Cache leeren und festes Neuladen aus, um sicherzustellen, dass Ihr Service Worker aktualisiert wird.
  6. Setzen Sie die Drop-down-Liste Drosselung wieder auf Offline.
  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-Benutzeroberfläche im Browser.

Berechtigung zum Senden von Benachrichtigungen anfordern

Der Einfachheit halber enthält die Offlineseite unter views/index_offline.html bereits den Code zum Anfordern von Benachrichtigungsberechtigungen in einem Skriptblock am unteren Rand:

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. Diese ruft Notification.requestPermission() auf, um die standardmäßige Aufforderung für Browserberechtigungen anzuzeigen. Das Promise wird mit der vom Nutzer ausgewählten Berechtigung aufgelöst. Diese kann entweder granted, denied oder default sein.
  • Gibt die aufgelöste Berechtigung an showOfflineText() weiter, damit dem Nutzer der entsprechende Text angezeigt werden kann.

Offline-Suchanfragen beibehalten und erneut versuchen, wenn Sie wieder online sind

Implementieren Sie als Nächstes die Workbox-Hintergrundsynchronisierung, um Offlineabfragen beizubehalten. So können sie wiederholt werden, wenn der Browser feststellt, dass wieder eine Verbindung besteht.

  1. public/sw.js zur Bearbeitung öffnen.
  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 wiederholt werden können. Diese Anfragen werden in IndexedDB beibehalten.
  • maxRetentionTime gibt an, wie lange eine Anfrage wiederholt werden kann. In diesem Fall haben wir 60 Minuten ausgewählt (nachdem sie gelöscht wird).
  • onSync ist der wichtigste Teil dieses Codes. Dieser Callback wird aufgerufen, sobald die Verbindung wiederhergestellt ist, sodass Anfragen in der Warteschlange abgerufen und dann aus dem Netzwerk abgerufen werden.
  • Die Netzwerkantwort wird dem offline-search-responses-Cache hinzugefügt und der &notification=true-Abfrageparameter angehängt, sodass dieser Cache-Eintrag erfasst werden kann, wenn ein Nutzer auf die Benachrichtigung klickt.

Um die Hintergrundsynchronisierung in Ihren Dienst zu integrieren, definieren Sie eine NetworkOnly-Strategie für Anfragen an die Such-URL (/search_action) und übergeben Sie die zuvor definierten bgSyncPlugin. Fügen Sie am Ende von public/sw.js den folgenden Code hinzu:

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 zum Netzwerk zu wechseln und wenn Anfragen fehlschlagen, die Hintergrundsynchronisierungslogik zu verwenden.

Fügen Sie als Nächstes am Ende von public/sw.js den folgenden Code ein, um eine Caching-Strategie für Anfragen von Benachrichtigungen zu definieren. Verwenden Sie eine CacheFirst-Strategie, 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 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. Wechseln Sie zurück zum anderen Tab, auf dem Ihre App ausgeführt wird.
  2. Setzen Sie die Drop-down-Liste Drosselung wieder auf Online.
  3. Drücken Sie in Chrome die Schaltfläche Zurück, um zur Suchseite zurückzukehren.
  4. Halten Sie die Schaltfläche Aktualisieren in Chrome lange gedrückt und wählen Sie Cache leeren und festes Neuladen aus, um sicherzustellen, dass Ihr Service Worker aktualisiert wird.
  5. Setzen Sie die Drop-down-Liste Drosselung wieder auf Offline.
  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 von 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. Setzen Sie die Drop-down-Liste Drosselung wieder auf Online.

Sobald die Verbindung wiederhergestellt ist, wird eine Benachrichtigung angezeigt:

Screenshot des gesamten Offline-Ablaufs

Fazit

Workbox bietet viele integrierte Funktionen, mit denen Ihre PWAs stabiler und interaktiver werden. In diesem Codelab haben Sie erfahren, wie Sie die Background Sync API mithilfe der Workbox-Abstraktion implementieren, um sicherzustellen, dass Offline-Nutzeranfragen nicht verloren gehen und wiederhergestellt werden können, sobald die Verbindung wiederhergestellt ist. Die Demo ist eine einfache Such-App. Sie können jedoch eine ähnliche Implementierung für komplexere Szenarien und Anwendungsfälle verwenden, z. B. Chat-Apps oder das Posten von Nachrichten in sozialen Netzwerken.