Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.
Dieser Artikel bietet Informationen zum Einstieg in Service Worker, einschließlich der grundlegenden Architektur, der Registrierung eines Service Workers, des Installations- und Aktivierungsprozesses für einen neuen Service Worker, der Aktualisierung Ihres Service Workers, der Cache-Kontrolle und benutzerdefinierten Antworten, alles im Kontext einer Anwendung mit Offline-Funktionalität.
Ein übergeordnetes Problem, mit dem Webnutzer seit Jahren zu kämpfen haben, ist der Verlust von Konnektivität. Die beste Webanwendung der Welt bietet ein schlechtes Benutzererlebnis, wenn Sie sie nicht herunterladen können. Es gab verschiedene Versuche, Technologien zu schaffen, um dieses Problem zu lösen, und einige der Probleme wurden gelöst. Aber das übergeordnete Problem war, dass es keinen guten allgemeinen Kontrollmechanismus für Asset-Caching und benutzerdefinierte Netzwerk-Anfragen gab.
Service Worker beheben diese Probleme. Durch die Verwendung eines Service Workers können Sie eine Anwendung so einrichten, dass sie zuerst zwischengespeicherte Assets verwendet und somit eine Standarderfahrung bietet, selbst wenn sie offline ist, bevor dann mehr Daten aus dem Netzwerk abgerufen werden (häufig als “offline first” bezeichnet). Dies ist bereits mit nativen Apps verfügbar, was einer der Hauptgründe dafür ist, dass native Apps häufig Web-Apps vorgezogen werden.
Ein Service Worker fungiert wie ein Proxy-Server, der es Ihnen ermöglicht, Anfragen und Antworten zu modifizieren und sie durch Elemente aus seinem eigenen Cache zu ersetzen.
Service Worker sind standardmäßig in allen modernen Browsern aktiviert. Um Code unter Verwendung von Service Workern auszuführen, müssen Sie Ihren Code über HTTPS bereitstellen — Service Worker sind aus Sicherheitsgründen darauf beschränkt, über HTTPS auszuführen. Ein Server, der HTTPS unterstützt, ist notwendig. Um Experimente zu hosten, können Sie Dienste wie GitHub, Netlify, Vercel usw. verwenden. Um die lokale Entwicklung zu erleichtern, wird localhost von Browsern ebenfalls als sicherer Ursprung betrachtet.
Mit Service Workern werden im Allgemeinen die folgenden Schritte für die grundlegende Einrichtung beobachtet:
Hier ist eine Zusammenfassung der verfügbaren Service Worker-Ereignisse:
Um einfach die Grundlagen zu demonstrieren, wie ein Service Worker registriert und installiert wird, haben wir eine Demo namens einfacher Service Worker erstellt, die eine einfache Lego-Bildergalerie von Star Wars darstellt. Es verwendet eine auf Versprechungen basierende Funktion, um Bilddaten aus einem JSON-Objekt zu lesen und die Bilder mit fetch() zu laden, bevor die Bilder in einer Linie auf der Seite angezeigt werden. Wir haben die Dinge bisher statisch gehalten. Es registriert, installiert und aktiviert auch einen Service Worker.
Sie können den Quellcode auf GitHub und den einfachen Service Worker live laufend sehen.
Der erste Codeblock in der JavaScript-Datei unserer App — app.js — sieht wie folgt aus. Dies ist unser Einstiegspunkt in die Nutzung von Service Workern.
Dies registriert einen Service Worker, der in einem Worker-Kontext läuft und somit keinen Zugriff auf das DOM hat.
Ein einzelner Service Worker kann viele Seiten kontrollieren. Jedes Mal, wenn eine Seite innerhalb Ihres Bereichs geladen wird, wird der Service Worker gegen diese Seite installiert und arbeitet daran. Beachten Sie daher, dass Sie vorsichtig mit globalen Variablen im Skript des Service Workers sein müssen: Jede Seite erhält nicht ihren eigenen einzigartigen Worker.
Hinweis: Eine großartige Sache an Service Workern ist, dass, wenn Sie Feature-Erkennung wie oben gezeigt verwenden, Browser, die Service Worker nicht unterstützen, einfach Ihre App online in der normalen erwarteten Weise verwenden können.
Ein Service Worker schlägt aus einem der folgenden Gründe fehl, sich zu registrieren:
Nachdem Ihr Service Worker registriert ist, wird der Browser versuchen, den Service Worker für Ihre Seite/Ihr Site zu installieren und dann zu aktivieren.
Das install-Ereignis ist das erste Ereignis, das bei der Installation oder Aktualisierung des Service Workers ausgelöst wird. Es wird nur einmal ausgelöst, unmittelbar nachdem die Registrierung erfolgreich abgeschlossen ist, und wird in der Regel verwendet, um die Offline-Caching-Fähigkeiten Ihres Browsers mit den Assets zu befüllen, die Sie benötigen, um Ihre App offline auszuführen. Dazu verwenden wir die Speicher-API von Service Worker — cache — ein globales Objekt auf dem Service Worker, das es uns ermöglicht, durch Antworten ausgelieferte Assets zu speichern, benannt nach ihren Anfragen. Diese API funktioniert ähnlich wie der Standardcache des Browsers, ist jedoch spezifisch für Ihre Domain. Die Inhalte des Caches werden so lange gespeichert, bis Sie sie löschen.
So geht unser Service Worker mit dem install-Ereignis um:
Hinweis: Die Web Storage API (localStorage) funktioniert auf ähnliche Weise wie der Service Worker-Cache, ist jedoch synchron, daher nicht in Service Workern erlaubt.
Hinweis: IndexedDB kann innerhalb eines Service Workers für die Datenspeicherung verwendet werden, wenn Sie es benötigen.
Jetzt haben Sie Ihre Website-Ressourcen im Cache, Sie müssen den Service Workern mitteilen, etwas mit den zwischengespeicherten Inhalten zu tun. Dies wird mit dem fetch-Ereignis getan.
Ein fetch-Ereignis wird jedes Mal ausgelöst, wenn eine Ressource, die von einem Service Worker kontrolliert wird, abgerufen wird, was die Dokumente im angegebenen Bereich und alle in diesen Dokumenten referenzierten Ressourcen einschließt (zum Beispiel, wenn index.html eine abgekoppelte Anfrage für das Einbetten eines Bildes macht, geht das trotzdem durch seinen Service Worker).
Sie können einen fetch-Ereignis-Listener zum Service Worker anfügen und dann die Methode respondWith() auf dem Ereignis aufrufen, um Ihre HTTP-Antworten zu kapern und mit Ihrem eigenen Inhalt zu aktualisieren.
Wir könnten damit beginnen, mit der Ressource zu antworten, deren URL mit der der Netzwerk-Anfrage übereinstimmt, in jedem Fall:
caches.match(event.request) ermöglicht es uns, jede Ressource, die aus dem Netzwerk angefordert wird, mit der entsprechenden im Cache verfügbaren Ressource abzugleichen, wenn eine passende verfügbar ist. Das Matching erfolgt über URL und verschiedene Header, genau wie bei normalen HTTP-Anfragen.
caches.match(event.request) ist also großartig, wenn es eine Übereinstimmung im Service Worker-Cache gibt, aber was ist mit Fällen, in denen es keine Übereinstimmung gibt? Wenn wir keinen Ausfallhandling bieten, würde unser Versprechen mit undefined aufgelöst und wir würden nichts zurückbekommen.
Nachdem wir die Antwort aus dem Cache getestet haben, können wir auf eine normale Netzwerk-Anfrage zurückgreifen:
Wenn die Ressourcen nicht im Cache sind, werden sie aus dem Netzwerk angefordert.
Mit einer aufwändigeren Strategie könnten wir nicht nur die Ressource aus dem Netzwerk anfordern, sondern sie auch in den Cache speichern, damit spätere Anfragen für diese Ressource auch offline abgerufen werden können. Dies würde bedeuten, dass, wenn zusätzliche Bilder zur Star Wars-Galerie hinzugefügt würden, unsere App automatisch diese laden und cachen könnte. Das folgende Snippet implementiert eine solche Strategie:
Wenn die Anforderungs-URL nicht im Cache verfügbar ist, fordern wir die Ressource mit await fetch(request) aus der Netzwerk-Anfrage an. Danach legen wir ein Klon der Antwort in den Cache. Die putInCache()-Funktion verwendet caches.open('v1') und cache.put(), um die Ressource in den Cache zu legen. Die Originalantwort wird an den Browser zurückgegeben, um sie an die aufrufende Seite zu übergeben.
Das Klonen der Antwort ist notwendig, weil Anforderungs- und Antworstreams nur einmal gelesen werden können. Um die Antwort an den Browser zurückzugeben und sie in den Cache zu legen, müssen wir sie klonen. Das Original wird an den Browser zurückgegeben und der Klon in den Cache gesendet. Beide werden jeweils einmal gelesen.
Was etwas seltsam aussehen könnte, ist, dass das von putInCache() zurückgegebene Versprechen nicht erwartet wird. Der Grund ist, dass wir nicht warten wollen, bis der Antwortklon dem Cache hinzugefügt wurde, bevor eine Antwort zurückgegeben wird. Wir müssen jedoch event.waitUntil() auf dem Versprechen aufrufen, um sicherzustellen, dass der Service Worker nicht beendet wird, bevor der Cache gefüllt ist.
Das einzige Problem, das wir jetzt haben, ist, dass, wenn die Anfrage nichts im Cache findet und das Netzwerk nicht verfügbar ist, unsere Anfrage dennoch fehlschlägt. Lassen Sie uns ein Standard-Fallback bereitstellen, damit der Benutzer zumindest etwas erhält, egal was passiert:
Wir haben uns für dieses Fallback-Bild entschieden, weil die einzigen Updates, die wahrscheinlich fehlschlagen, neue Bilder sind, da alles andere für die Installation im install-Ereignis-Listener, den wir zuvor gesehen haben, abhängig ist.
Wenn aktiviert, startet die Funktion Navigation Preload das Herunterladen von Ressourcen, sobald die Fetch-Anfrage gestellt wird, und parallel zur Aktivierung des Service Workers. Dies stellt sicher, dass der Download sofort bei der Navigation zu einer Seite beginnt, anstatt auf die Aktivierung des Service Workers warten zu müssen. Diese Verzögerung tritt relativ selten auf, ist jedoch unvermeidlich, wenn sie auftritt und kann erheblich sein.
Zuerst muss die Funktion während der Aktivierung des Service Workers aktiviert werden, unter Verwendung von registration.navigationPreload.enable():
Verwenden Sie dann event.preloadResponse, um im fetch-Ereignishandler auf das Herunterladen der vorab geladenen Ressource zu warten.
In Fortsetzung des Beispiels aus den vorhergehenden Abschnitten fügen wir den Code ein, um auf die vorab geladene Ressource zu warten, nachdem der Cache überprüft wurde und bevor eine Anfrage an das Netzwerk gesendet wird, falls dies nicht gelingt.
Der neue Prozess ist:
Beachten Sie, dass wir in diesem Beispiel für die Ressource dieselben Daten herunterladen und cachen, unabhängig davon, ob sie "normal" oder vorab geladen heruntergeladen wird. Sie können stattdessen wählen, bei der Vorabladung eine andere Ressource herunterzuladen und zu cachen. Weitere Informationen finden Sie unter NavigationPreloadManager > Benutzerdefinierte Antworten.
Wenn Ihr Service Worker zuvor installiert wurde, aber dann eine neue Version des Workers bei einem Refresh oder einer Seitenladung verfügbar ist, wird die neue Version im Hintergrund installiert, aber noch nicht aktiviert. Sie wird nur aktiviert, wenn keine Seiten mehr geladen sind, die noch den alten Service Worker verwenden. Sobald keine solchen Seiten mehr geladen sind, aktiviert sich der neue Service Worker.
Hinweis: Es ist möglich, dies zu umgehen, indem Clients.claim() verwendet wird.
Sie möchten Ihren install-Ereignis-Listener im neuen Service Worker in etwas wie dies aktualisieren (beachten Sie die neue Versionsnummer):
Während der Service Worker installiert wird, ist die vorherige Version noch für Abrufe verantwortlich. Die neue Version wird im Hintergrund installiert. Wir nennen den neuen Cache v2, damit der vorherige v1-Cache nicht gestört wird.
Wenn keine Seiten mehr die vorherige Version verwenden, wird der neue Worker aktiviert und ist für Abrufe verantwortlich.
Wie wir im letzten Abschnitt gesehen haben, erstellen Sie, wenn Sie einen Service Worker auf eine neue Version aktualisieren, einen neuen Cache in dessen install-Ereignis-Handler. Solange es offene Seiten gibt, die von der vorherigen Version des Workers kontrolliert werden, müssen Sie beide Caches behalten, da die vorherige Version ihren Cache benötigt. Sie können das activate-Ereignis verwenden, um Daten aus den vorherigen Caches zu entfernen.
Versprechen, die an waitUntil() übergeben werden, blockieren andere Ereignisse bis zum Abschluss, sodass Sie sicher sein können, dass Ihr Bereinigungsprozess abgeschlossen ist, bis Sie Ihr erstes fetch-Ereignis im neuen Service Worker erhalten.
Der Bauplan für ein besseres Internet.
Besuche die gemeinnützige Muttergesellschaft der Mozilla Corporation, die Mozilla Foundation.
Teile dieses Inhalts sind ©1998–2026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfügbar unter einer Creative-Commons-Lizenz.