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 Serverendpunkt 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 Zum Bearbeiten Remix, damit das Projekt bearbeitet werden kann.
  • Wenn Sie sich eine Vorschau der Website ansehen möchten, klicken Sie auf App ansehen. Drücken Sie dann Vollbild Vollbild

Überprüfen Sie in dem neuen Tab, der gerade geöffnet wurde, wie sich die Website verhält, wenn sie offline ist:

  1. Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Option + J“ auf einem Mac), um die Entwicklertools zu öffnen.
  2. Klicken Sie auf den Tab Netzwerk.
  3. Öffne die Chrome-Entwicklertools und wähle den Bereich „Network“ (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 Standardfehlerseite des Browsers wird angezeigt:

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

Fallback-Antwort angeben

Der Service Worker enthält den Code, um die Offlineseite der Precache-Liste hinzuzufügen, damit sie beim Service Worker install-Ereignis immer im Cache gespeichert werden kann.

Normalerweise müssen Sie Workbox anweisen, diese Datei zum Zeitpunkt der Erstellung der 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 erledigt. Dazu dient 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 anzuzeigen, drücken Sie Quelltext anzeigen.
  2. Fügen Sie am Ende von public/sw.js den folgenden Code 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 für alle Anfragen gilt.
  • Deklariert einen globalen Fehler-Handler, indem workbox.routing.setCatchHandler() zum Verwalten fehlgeschlagener Anfragen aufgerufen wird. Bei Anfragen für Dokumente wird eine Offline-HTML-Fallback-Seite zurückgegeben.

So testen Sie diese Funktionalität:

  1. Kehren Sie zum anderen Tab zurück, auf dem Ihre App ausgeführt wird.
  2. Setze die Drop-down-Liste Dhrottling (Drosselung) auf Online zurück.
  3. Drücken Sie in Chrome die Taste 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 Chrome-Schaltfläche Aktualisieren lange gedrückt und wählen Sie Cache leeren und neu laden um sicherzustellen, dass Ihr Service Worker aktualisiert wird.
  6. Setzen Sie die Drop-down-Liste Dhrottling (Drosselung) wieder auf Offline (Offline).
  7. Geben Sie eine Suchanfrage ein und klicken Sie noch einmal auf die Schaltfläche Suchen.

Hier sehen Sie die HTML-Seite des Fallbacks:

Screenshot der benutzerdefinierten Offline-UX im Browser.

Berechtigung zum Anfordern von Benachrichtigungen

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

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 requestNotificationPermission()-Funktion aufgerufen. Diese ruft Notification.requestPermission() auf, um die standardmäßige Berechtigungsaufforderung des Browsers anzuzeigen. Das Promise wird mit der vom Nutzer ausgewählten Berechtigung aufgelöst. Diese kann granted, denied oder default sein.
  • Übergibt die geklärte Berechtigung an showOfflineText(), um dem Nutzer den entsprechenden Text anzuzeigen.

Offlineabfragen beibehalten und erneut versuchen, wenn sie wieder online sind

Als Nächstes implementieren Sie die Workbox Background Sync, um Offlineabfragen beizubehalten, damit sie erneut ausgeführt werden können, wenn der Browser erkennt, dass eine Verbindung wiederhergestellt wurde.

  1. public/sw.js zum Bearbeiten ö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 gewählt. Danach wird die Anzeige verworfen.
  • onSync ist der wichtigste Teil dieses Codes. Dieser Callback wird aufgerufen, sobald die Verbindung wieder hergestellt 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 abgerufen werden kann, wenn ein Nutzer auf die Benachrichtigung klickt.

Um die Hintergrundsynchronisierung in Ihren Dienst zu integrieren, definieren Sie eine Strategie vom Typ NetworkOnly für Anfragen an die Such-URL (/search_action) und übergeben Sie den zuvor definierten bgSyncPlugin. Fügen Sie am Ende von public/sw.js den folgenden Code 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],
  }),
);

Damit wird Workbox angewiesen, immer zum Netzwerk zu wechseln und, wenn Anfragen fehlschlagen, die Hintergrundsynchronisierungslogik zu verwenden.

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

Sobald die Verbindung wiederhergestellt ist, wird eine Benachrichtigung angezeigt:

Screenshot des vollständigen Offline-Ablaufs

Fazit

Workbox bietet viele integrierte Funktionen, die Ihre PWAs widerstandsfähiger und interaktiver machen. In diesem Codelab haben Sie erfahren, wie Sie die Background Sync API über die Workbox-Abstraktion implementieren, um sicherzustellen, dass Offline-Nutzerabfragen nicht verloren gehen und erneut versucht 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 wie Chat-Apps oder das Posten von Nachrichten in einem sozialen Netzwerk verwenden.