Fallback-Antworten verwalten

In bestimmten Situationen kann es sinnvoll sein, eine Fallback-Antwort im Cache zu speichern, falls der Nutzer offline ist. Die Implementierung eines Fallbacks ist eine Alternative zum Caching-Verhalten, das durch Strategien wie „Network-First“ oder „Stale-while-revalid“ bereitgestellt wird.

Ein Fallback ist eine allgemeine, allgemeingültige Antwort, die ein besserer Platzhalter ist als die, die der Browser standardmäßig bereitstellen würde, wenn eine Anfrage fehlschlägt. Dazu einige Beispiele:

  • Eine Alternative zum Platzhalter für „fehlendes Bild“.
  • Eine HTML-Alternative zur Standardseite "Keine Netzwerkverbindung verfügbar".

Nur Offlineseite

Wenn Sie ausschließlich eine benutzerdefinierte Offline-HTML-Seite angeben müssen, finden Sie hier ein Grundlegendes, dem Sie folgen können:

import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

setDefaultHandler(new NetworkOnly());

offlineFallback();

Der obige Code verwendet setDefaultHandler, um eine reine Netzwerkstrategie als Standard für alle Routen zu verwenden. Anschließend wird das Schema offlineFallback ausgeführt, um für den Fall, dass ein Fehler auftritt, das Offline-Fallback bereitzustellen. Im Rezept wird davon ausgegangen, dass die Offline-Fallback-HTML-Datei den Namen offline.html hat und vom Stammverzeichnis Ihres Webservers bereitgestellt wird.

Umfassende Fallbacks

Immer wenn ein Netzwerkfehler oder ein Cache-Fehler auftritt, lehnen die von workbox-strategies angebotenen Caching-Strategien immer wieder ab. Dies fördert das Muster eines globalen „Catch“-Handlers zur Behandlung von Fehlern in einer einzelnen Handler-Funktion. So können Sie verschiedene Fallbacks für verschiedene request.destination-Werte anbieten.

Im folgenden Beispiel wird das Rezept warmStrategyCache von workbox-recipes verwendet und ein Catch-Handler festgelegt, um Elemente bereitzustellen, die vorab im Laufzeitcache zwischengespeichert werden. Das Precaching von Fallbacks ist jedoch möglicherweise besser für Ihre Anwendung geeignet:

import {warmStrategyCache} from 'workbox-recipes';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';

// Fallback assets to cache
const FALLBACK_HTML_URL = '/offline.html';
const FALLBACK_IMAGE_URL = '/images/image-not-found.jpg';
const FALLBACK_STRATEGY = new CacheFirst();

// Warm the runtime cache with a list of asset URLs
warmStrategyCache({
  urls: [FALLBACK_HTML_URL, FALLBACK_IMAGE_URL],
  strategy: FALLBACK_STRATEGY,
});

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // The warmStrategyCache recipe is used to add the fallback assets ahead of
  // time to the runtime cache, and are served in the event of an error below.
  // Use `event`, `request`, and `url` to figure out how to respond, or
  // use request.destination to match requests for specific resource types.
  switch (request.destination) {
    case 'document':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_HTML_URL});

    case 'image':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_IMAGE_URL});

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

Im nächsten Schritt werden Fallback-Antworten mithilfe von injectManifest mit den Build-Tools von Workbox vorab im Cache gespeichert und bei einem Fehler mit der matchPrecache-Methode als Fallback verwendet.

import {matchPrecache, precacheAndRoute} from 'workbox-precaching';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

// Optional: use the injectManifest mode of one of the Workbox
// build tools to precache a list of URLs, including fallbacks.
precacheAndRoute(self.__WB_MANIFEST);

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // Fallback assets are precached when the service worker is installed, and are
  // served in the event of an error below. Use `event`, `request`, and `url` to
  // figure out how to respond, or use request.destination to match requests for
  // specific resource types.
  switch (request.destination) {
    case 'document':
      // FALLBACK_HTML_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_HTML_URL);

    case 'image':
      // FALLBACK_IMAGE_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_IMAGE_URL);

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

Ein Beispiel für die zweite Fallback-Einrichtung ist, wenn eine Seite vorab im Cache gespeichert wurde, Bilder (oder andere Assets), die von der Seite angefordert wurden, jedoch nicht. Die Seite kann auch dann aus dem Cache gelesen werden, wenn der Nutzer offline ist. Falls jedoch ein Netzwerkfehler auftritt, können Ersatzplatzhalter oder alternative Funktionen bereitgestellt werden.

Laufzeitcache aufwärmen

Workbox unterhält separate Caches für das Precaching und für die Laufzeit-Caches. Es kann Situationen geben, in denen Sie etwas im Voraus im Cache speichern möchten, ohne auf Precaching angewiesen zu sein, da Sie bei Aktualisierungen des Precache-Manifests einen aktualisierten Service Worker bereitstellen müssen.

Um den Laufzeit-Cache vorab mit Assets zu füllen, können Sie das warmStrategyCache-Schema von workbox-recipes verwenden. Intern wird bei dieser Strategie Cache.addAll beim Ereignis install eines Service Workers aufgerufen.

import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';

// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = [
  '/offline.html',
];

warmStrategyCache({urls, strategy});

Fazit

Die Verwaltung von Fallback-Antworten für fehlgeschlagene Anfragen ist etwas Arbeit. Mit etwas Vorausplanung können Sie Ihre Webanwendung aber so einrichten, dass sie Inhalte und Funktionen auch dann bereitstellt, wenn der Nutzer offline ist.