Strategien für das Service Worker-Caching

Bisher wurden nur Erwähnungen und kleine Code-Snippets der Cache-Oberfläche. Um Service Worker effektiv zu nutzen, müssen Sie eine oder mehrere Caching-Strategien anwenden. Dafür sollten Sie sich ein wenig mit der Cache-Oberfläche auskennen.

Eine Caching-Strategie ist eine Interaktion zwischen dem fetch-Ereignis eines Service Workers und der Cache-Schnittstelle. Wie eine Caching-Strategie geschrieben wird, hängt davon ab: Es ist z. B. besser, Anfragen für statische Assets anders zu verarbeiten als für Dokumente, Dies wirkt sich auf die Zusammensetzung einer Caching-Strategie aus.

Bevor wir uns mit den Strategien befassen, Sehen wir uns kurz an, was die Cache-Oberfläche nicht ist, was sie ist, und eine kurze Übersicht über einige der Methoden zum Verwalten von Service Worker-Caches.

Die Cache-Schnittstelle im Vergleich zum HTTP-Cache

Wenn Sie noch nicht mit der Cache-Oberfläche gearbeitet haben, mag es verlockend sein, es als eine Art oder zumindest mit dem HTTP-Cache zusammenhängen. Das stimmt nicht.

  • Die Cache-Schnittstelle ist ein Caching-Mechanismus, der vollständig vom HTTP-Cache getrennt ist.
  • Egal Cache-Control Die verwendete Konfiguration zur Beeinflussung des HTTP-Cache hat keinen Einfluss darauf, welche Assets in der Cache-Oberfläche gespeichert werden.

Stellen Sie sich Browser-Caches als mehrschichtige Elemente vor. Der HTTP-Cache ist ein Low-Level-Cache, der von Schlüssel/Wert-Paaren mit in HTTP-Headern ausgedrückten Anweisungen gesteuert wird.

Im Gegensatz dazu ist die Cache-Schnittstelle ein übergeordneter Cache, der von einer JavaScript API gesteuert wird. Dies bietet mehr Flexibilität als bei relativ vereinfachten HTTP-Schlüssel/Wert-Paaren, und macht Caching-Strategien erst möglich. Einige wichtige API-Methoden im Zusammenhang mit Service Worker-Caches sind:

  • CacheStorage.open um eine neue Cache-Instanz zu erstellen.
  • Cache.add und Cache.put um Netzwerkantworten in einem Service Worker-Cache zu speichern.
  • Cache.match um eine im Cache gespeicherte Antwort in einer Cache-Instanz zu finden.
  • Cache.delete , um eine im Cache gespeicherte Antwort aus einer Cache-Instanz zu entfernen.

Das sind nur einige Beispiele. Es gibt noch weitere nützliche Methoden, aber dies sind die grundlegenden, die wir später in diesem Leitfaden verwenden werden.

Das einfache fetch-Ereignis

Die andere Hälfte der Caching-Strategie ist die fetch-Ereignis. Bisher haben Sie in dieser Dokumentation etwas über das "Abfangen von Netzwerkanfragen", und im Ereignis fetch innerhalb eines Service Workers geschieht dies:

// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';

self.addEventListener('install', (event) => {
  event.waitUntil(caches.open(cacheName));
});

self.addEventListener('fetch', async (event) => {
  // Is this a request for an image?
  if (event.request.destination === 'image') {
    // Open the cache
    event.respondWith(caches.open(cacheName).then((cache) => {
      // Respond with the image from the cache or from the network
      return cache.match(event.request).then((cachedResponse) => {
        return cachedResponse || fetch(event.request.url).then((fetchedResponse) => {
          // Add the network response to the cache for future visits.
          // Note: we need to make a copy of the response to save it in
          // the cache and use the original as the request response.
          cache.put(event.request, fetchedResponse.clone());

          // Return the network response
          return fetchedResponse;
        });
      });
    }));
  } else {
    return;
  }
});

Dies ist ein Spielzeugbeispiel – eines, das Sie selbst in Aktion sehen können, Es bietet einen Einblick in die Fähigkeiten Service Workers. Mit dem Code oben wird Folgendes ausgeführt:

  1. Prüfen Sie das Attribut destination der Anfrage, um festzustellen, ob es sich um eine Image-Anfrage handelt.
  2. Wenn sich das Bild im Service Worker-Cache befindet, stellen Sie es von dort bereit. Falls nicht, rufen Sie das Image aus dem Netzwerk ab. die Antwort im Cache speichern und die Netzwerkantwort zurückgeben.
  3. Alle anderen Anfragen werden ohne Interaktion mit dem Cache über den Service Worker geleitet.

Das event-Objekt eines Abrufs enthält einen request-Property mit einigen nützlichen Informationen, die Ihnen helfen, die Art der Anfrage zu ermitteln:

  • url, Dies ist die URL für die Netzwerkanfrage, die derzeit vom Ereignis fetch verarbeitet wird.
  • method, also die Anfragemethode (z.B. GET oder POST).
  • mode, der den Modus der Anfrage beschreibt. Der Wert 'navigate' wird häufig verwendet, um Anfragen für HTML-Dokumente von anderen Anfragen zu unterscheiden.
  • destination, der den Typ der angeforderten Inhalte so beschreibt, dass die Dateiendung des angefragten Assets nicht verwendet wird.

Auch hier ist Asynchronität der Name des Spiels. Sie erinnern sich, dass das Ereignis install Folgendes bietet: event.waitUntil -Methode, die ein Promise aufgreift und auf dessen Auflösung wartet, bevor die Aktivierung fortgesetzt wird. Das fetch-Ereignis bietet ähnliche Methode event.respondWith mit der Sie das Ergebnis eines asynchronen fetch Anfrage oder eine vom Cache-Interface zurückgegebene Antwort match-Methode.

Caching-Strategien

Sie haben sich nun mit Cache-Instanzen und dem fetch-Event-Handler vertraut gemacht. sind Sie bereit, sich mit einigen Service-Worker-Caching-Strategien vertraut zu machen. Die Möglichkeiten sind praktisch endlos, dieser Leitfaden sich auf die Strategien, die mit Workbox ausgeliefert werden, damit Sie einen Eindruck davon erhalten, was bei Workbox vor sich geht.

Nur Cache

Zeigt den Fluss von der Seite über den Service Worker zum Cache.

Beginnen wir mit einer einfachen Caching-Strategie namens „Nur Cache“. Wenn der Service Worker die Seite verwaltet, werden übereinstimmende Anfragen nur im Cache gespeichert. Das bedeutet, dass alle im Cache gespeicherten Assets vorab im Cache gespeichert werden müssen, damit das Muster funktioniert. und dass diese Assets erst dann im Cache aktualisiert werden, wenn der Service Worker aktualisiert wurde.

// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';

// Assets to precache
const precachedAssets = [
  '/possum1.jpg',
  '/possum2.jpg',
  '/possum3.jpg',
  '/possum4.jpg'
];

self.addEventListener('install', (event) => {
  // Precache assets on install
  event.waitUntil(caches.open(cacheName).then((cache) => {
    return cache.addAll(precachedAssets);
  }));
});

self.addEventListener('fetch', (event) => {
  // Is this one of our precached assets?
  const url = new URL(event.request.url);
  const isPrecachedRequest = precachedAssets.includes(url.pathname);

  if (isPrecachedRequest) {
    // Grab the precached asset from the cache
    event.respondWith(caches.open(cacheName).then((cache) => {
      return cache.match(event.request.url);
    }));
  } else {
    // Go to the network
    return;
  }
});

Oben ist ein Array von Assets bei der Installation vorab im Cache gespeichert. Wenn der Service Worker Abrufe verarbeitet, prüfen wir, ob die vom fetch-Ereignis verarbeitete Anfrage-URL im Array der vorab im Cache gespeicherten Assets enthalten ist. Ist dies der Fall, nehmen wir die Ressource aus dem Cache und überspringen das Netzwerk. Andere Anfragen werden an das Netzwerk weitergeleitet, und nur das Netzwerk. Um diese Strategie in Aktion zu sehen, sehen Sie sich diese Demo bei geöffneter Konsole an.

Nur Netzwerk

Zeigt den Fluss von der Seite über den Service Worker zum Netzwerk.

Das Gegenteil von "Nur Cache" ist "Nur Netzwerk", Dabei wird eine Anfrage ohne Interaktion mit dem Service Worker-Cache durch einen Service Worker an das Netzwerk übergeben. Das ist eine gute Strategie, um für die Aktualität der Inhalte zu sorgen. Der Kompromiss ist jedoch, dass es nie funktioniert, wenn der Nutzer offline ist.

Wenn dafür gesorgt wird, dass eine Anfrage an das Netzwerk weitergeleitet wird, wird für eine übereinstimmende Anfrage nicht event.respondWith aufgerufen. Wenn Sie explizit etwas sagen möchten, kannst du für Anfragen, die du an das Netzwerk weiterleiten möchtest, ein leeres return; in deinem fetch-Ereignis-Callback schlagen. Dies geschieht in der Einstellung "Nur Cache". für nicht vorab im Cache gespeicherte Anfragen.

Zuerst Cache, Fallback auf Netzwerk

Zeigt den Fluss von der Seite zum Service Worker, zum Cache und dann zum Netzwerk an, wenn er sich nicht im Cache befindet.

Bei dieser Strategie wird die Sache etwas stärker. Bei übereinstimmenden Anfragen läuft der Vorgang so ab:

  1. Die Anfrage erreicht den Cache. Wenn sich das Asset im Cache befindet, können Sie es von dort aus bereitstellen.
  2. Wenn sich die Anfrage nicht im Cache befindet, rufen Sie das Netzwerk auf.
  3. Sobald die Netzwerkanfrage abgeschlossen ist, fügen Sie sie dem Cache hinzu. und die Antwort vom Netzwerk zurückgeben.

Hier ist ein Beispiel für diese Strategie, die Sie in Live-Demo:

// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';

self.addEventListener('fetch', (event) => {
  // Check if this is a request for an image
  if (event.request.destination === 'image') {
    event.respondWith(caches.open(cacheName).then((cache) => {
      // Go to the cache first
      return cache.match(event.request.url).then((cachedResponse) => {
        // Return a cached response if we have one
        if (cachedResponse) {
          return cachedResponse;
        }

        // Otherwise, hit the network
        return fetch(event.request).then((fetchedResponse) => {
          // Add the network response to the cache for later visits
          cache.put(event.request, fetchedResponse.clone());

          // Return the network response
          return fetchedResponse;
        });
      });
    }));
  } else {
    return;
  }
});

Obwohl in diesem Beispiel nur Bilder behandelt werden, Diese Strategie eignet sich hervorragend für alle statischen Assets (z. B. CSS, JavaScript, Bilder und Schriftarten). insbesondere mit Hash-Versionen. Er bietet eine höhere Geschwindigkeit für unveränderliche Assets, da alle Prüfungen der Inhaltsaktualität auf dem Server, der vom HTTP-Cache ausgelöst werden könnte, übersprungen werden. Und was noch wichtiger ist: Alle im Cache gespeicherten Assets sind offline verfügbar.

Zuerst Netzwerk, Fallback auf Cache

Zeigt den Fluss von der Seite über den Service Worker zum Netzwerk und dann zum Cache, wenn das Netzwerk nicht verfügbar ist.

Wenn Sie „Zuerst Cache, Netzwerk dann auf dem Kopf, erhalten Sie die Meldung „Netzwerk zuerst, dann Cache“. Strategie. Das ist das, wonach es sich anhört:

  1. Sie suchen zuerst im Netzwerk eine Anfrage und platzieren die Antwort in den Cache.
  2. Wenn Sie später offline sind, greifen Sie im Cache auf die neueste Version dieser Antwort zurück.

Diese Strategie eignet sich hervorragend für HTML- oder API-Anfragen, wenn Sie online sind, möchten Sie die neueste Version einer Ressource, aber Sie möchten der neuesten verfügbaren Version Offline-Zugriff geben. Bei Anwendung auf HTML-Anfragen könnte das so aussehen:

// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';

self.addEventListener('fetch', (event) => {
  // Check if this is a navigation request
  if (event.request.mode === 'navigate') {
    // Open the cache
    event.respondWith(caches.open(cacheName).then((cache) => {
      // Go to the network first
      return fetch(event.request.url).then((fetchedResponse) => {
        cache.put(event.request, fetchedResponse.clone());

        return fetchedResponse;
      }).catch(() => {
        // If the network is unavailable, get
        return cache.match(event.request.url);
      });
    }));
  } else {
    return;
  }
});

Sie können dies in einer Demo ausprobieren. Rufen Sie zuerst die Seite auf. Möglicherweise müssen Sie die Seite neu laden, bevor die HTML-Antwort im Cache abgelegt wird. In Ihren Entwicklertools eine Offlineverbindung simulieren, und aktualisieren Sie die Seite. Die letzte verfügbare Version wird sofort aus dem Cache bereitgestellt.

In Situationen, in denen Offlinefunktionen wichtig sind, Sie müssen diese Möglichkeit jedoch mit dem Zugriff auf die neueste Version eines Markups oder API-Daten in Einklang bringen. „Erstes Netzwerk, dann Cache“ ist eine solide Strategie, mit der Sie dieses Ziel erreichen.

Veraltete erneute Validierung

Zeigt den Fluss von der Seite zum Service Worker, zum Cache und dann vom Netzwerk zum Cache an.

Von den Strategien, die wir bisher behandelt haben, ist am komplexesten. Es ähnelt in gewisser Weise den letzten beiden Strategien, Das Verfahren priorisiert jedoch die Zugriffsgeschwindigkeit für eine Ressource, und im Hintergrund laufend aktualisiert. Diese Strategie sieht etwa so aus:

  1. Rufen Sie ein Asset aus dem Netzwerk ab, und die Netzwerkantwort zurückgeben.
  2. Bei nachfolgenden Anfragen muss das Asset zuerst aus dem Cache und dann im Hintergrund ausgeliefert werden. fordern Sie es noch einmal vom Netzwerk an und aktualisieren Sie den Cache-Eintrag des Assets.
  3. Bei späteren Anfragen erhalten Sie die letzte aus dem Netzwerk abgerufene Version, die im vorherigen Schritt in den Cache gestellt wurde.

Dies ist eine hervorragende Strategie für Dinge, die irgendwie wichtig sind, um auf dem Laufenden zu bleiben, aber nicht entscheidend sind. Denken Sie zum Beispiel an Avatare für eine Social-Media-Website. Sie werden aktualisiert, wenn Nutzende Die aktuelle Version ist jedoch nicht bei jeder Anfrage erforderlich.

// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';

self.addEventListener('fetch', (event) => {
  if (event.request.destination === 'image') {
    event.respondWith(caches.open(cacheName).then((cache) => {
      return cache.match(event.request).then((cachedResponse) => {
        const fetchedResponse = fetch(event.request).then((networkResponse) => {
          cache.put(event.request, networkResponse.clone());

          return networkResponse;
        });

        return cachedResponse || fetchedResponse;
      });
    }));
  } else {
    return;
  }
});

Dies sehen Sie in der Praxis unter eine weitere Live-Demo Achten Sie in den Entwicklertools auf den Tab „Network“ (Netzwerk) und den CacheStorage-Viewer (wenn die Entwicklertools Ihres Browsers über ein solches Tool verfügen).

Weiter gehts mit der Workbox!

Dieses Dokument schließt unsere Prüfung der Service Worker API ab. sowie zugehörige APIs, Sie haben also genug darüber gelernt, wie Sie Service Worker direkt einsetzen, um mit Workbox zu experimentieren.