Das Leben eines Servicemitarbeiters

Ohne Verständnis ihres Lebenszyklus ist es schwierig, zu wissen, was Service Worker machen. Ihr Innenleben wird undurchsichtig und sogar willkürlich wirken. Wie bei jeder anderen Browser-API ist auch das Verhalten der Service Worker klar definiert, und Offline-Anwendungen ermöglichen, und Updates zu ermöglichen, ohne die Nutzererfahrung zu beeinträchtigen.

Bevor Sie sich mit Workbox befassen, ist es wichtig, den Lebenszyklus des Service Workers zu verstehen, damit die Workbox sinnvoll ist.

Definition von Begriffen

Bevor Sie in den Service Worker-Lebenszyklus ist es sinnvoll, einige Begriffe zur Funktionsweise dieses Lebenszyklus zu definieren.

Kontrolle und Umfang

Das Konzept der Kontrolle ist entscheidend, um zu verstehen, wie Service Worker arbeiten. Eine Seite, die als von einem Service Worker gesteuert wird, ist eine Seite, die einem Service Worker ermöglicht, Netzwerkanfragen in seinem Namen abzufangen. Der Service Worker ist vorhanden und kann innerhalb eines bestimmten Bereichs für die Seite arbeiten.

Umfang

Der Bereich eines Service Workers wird durch seinen Standort auf einem Webserver bestimmt. Wenn ein Service Worker auf einer Seite unter /subdir/index.html ausgeführt wird und sich in /subdir/sw.js befindet, Der Geltungsbereich des Service Workers ist /subdir/. Dieses Beispiel zeigt das Konzept des Umfangs in Aktion:

  1. Navigieren zu https://service-worker-scope-viewer.glitch.me/subdir/index.html. Es wird eine Meldung angezeigt, dass die Seite von keinem Service Worker gesteuert wird. Auf dieser Seite wird jedoch ein Service Worker von https://service-worker-scope-viewer.glitch.me/subdir/sw.js registriert.
  2. Lade die Seite neu. Da der Service Worker registriert und jetzt aktiv ist, die Seite gesteuert. Ein Formular mit dem Geltungsbereich des Service Workers, aktuellen Status und die zugehörige URL ist sichtbar. Hinweis: Ein erneutes Aktualisieren der Seite hat nichts mit dem Geltungsbereich zu tun. sondern auf den Lebenszyklus des Service Workers, der weiter unten erläutert wird.
  3. Gehen Sie jetzt zu https://service-worker-scope-viewer.glitch.me/index.html. Obwohl ein Service Worker bei diesem Ursprung registriert war, Sie sehen immer noch die Meldung, dass es keinen aktuellen Service Worker gibt. Das liegt daran, dass diese Seite nicht in den Bereich des registrierten Service Workers fällt.

Der Bereich legt fest, welche Seiten der Service Worker steuert. In diesem Beispiel bedeutet das, dass der aus /subdir/sw.js geladene Service Worker nur Seiten steuern kann, die sich in /subdir/ oder dessen Unterstruktur befinden.

Oben sehen Sie, wie der Umfang standardmäßig festgelegt wird. Der maximal zulässige Umfang kann jedoch überschrieben werden, indem das Attribut Service-Worker-Allowed-Antwortheader, sowie eine scope-Option zur Methode register.

Es sei denn, es gibt einen sehr guten Grund, den Service-Worker-Bereich auf eine Teilmenge eines Ursprungs zu beschränken, einen Service Worker aus dem Stammverzeichnis des Webservers laden, damit sein Umfang so breit wie möglich ist, müssen Sie sich keine Gedanken um den Service-Worker-Allowed-Header machen. Das ist für alle viel einfacher.

Kunde

Wenn gesagt wird, dass ein Service Worker eine Seite steuert, steuert er in Wirklichkeit einen Client. Ein Client ist jede geöffnete Seite, deren URL in den Bereich dieses Service Workers fällt. Im Einzelnen sind dies Instanzen eines WindowClient.

Lebenszyklus eines neuen Service Workers

Damit ein Service Worker eine Seite steuern kann, sie muss erst entstehen, sozusagen. Beginnen wir damit, was passiert, wenn ein neuer Service Worker für eine Website ohne aktiven Service Worker bereitgestellt wird.

Anmeldung

Die Registrierung ist der erste Schritt im Service Worker-Lebenszyklus:

<!-- In index.html, for example: -->
<script>
  // Don't register the service worker
  // until the page has fully loaded
  window.addEventListener('load', () => {
    // Is service worker available?
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').then(() => {
        console.log('Service worker registered!');
      }).catch((error) => {
        console.warn('Error registering service worker:');
        console.warn(error);
      });
    }
  });
</script>

Dieser Code wird im Hauptthread ausgeführt und führt Folgendes aus:

  1. Da der erste Besuch des Nutzers auf einer Website ohne registrierten Service Worker stattfindet, Warten Sie, bis die Seite vollständig geladen ist, bevor Sie eine registrieren. Dadurch werden Bandbreitenkonflikte vermieden, wenn der Service Worker Daten vorab im Cache speichert.
  2. Service Worker wird zwar gut unterstützt, aber Mit einer Schnellprüfung können Fehler in Browsern vermieden werden, in denen die Funktion nicht unterstützt wird.
  3. Wenn die Seite vollständig geladen ist und Service Worker unterstützt wird, registrieren Sie /sw.js.

Hier sind einige wichtige Punkte, die Sie verstehen sollten:

  • Service Worker sind nur über HTTPS oder localhost verfügbar.
  • Wenn der Inhalt eines Service Workers Syntaxfehler enthält, schlägt die Registrierung fehl und der Service Worker wird verworfen.
  • Erinnerung: Service Worker arbeiten innerhalb eines Bereichs. Hier bezieht sich der Bereich auf den gesamten Ursprung, da er aus dem Stammverzeichnis geladen wurde.
  • Zu Beginn der Registrierung wird der Service Worker-Status auf 'installing' festgelegt.

Nach Abschluss der Registrierung beginnt die Installation.

Installation

Ein Service Worker löst seine install-Veranstaltung nach der Registrierung. install wird nur einmal pro Service Worker aufgerufen und erst nach einer Aktualisierung noch einmal ausgelöst. Ein Callback für das install-Ereignis kann mit addEventListener im Geltungsbereich des Workers registriert werden:

// /sw.js
self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v1';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v1'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.bc7b80b7.css',
      '/css/home.fe5d0b23.css',
      '/js/home.d3cc4ba4.js',
      '/js/jquery.43ca4933.js'
    ]);
  }));
});

Dadurch wird eine neue Cache-Instanz erstellt und Assets werden vorab im Cache gespeichert. Wir werden später noch viele Gelegenheiten haben, über Precaching zu sprechen, Konzentrieren wir uns also auf die Rolle event.waitUntil event.waitUntil akzeptiert ein Versprechen, und wartet, bis das Versprechen gelöst ist. In diesem Beispiel werden mit dem Versprechen zwei asynchrone Vorgänge ausgeführt:

  1. Erstellt eine neue Cache-Instanz mit dem Namen 'MyFancyCache_v1'.
  2. Nachdem der Cache erstellt wurde, ein Array von Asset-URLs wird mithilfe der asynchronen addAll-Methode.

Die Installation schlägt fehl, wenn die an event.waitUntil übergebenen Promis: abgelehnt. In diesem Fall wird der Service Worker verworfen.

Wenn sich die Zusagen beheben, ist die Installation erfolgreich. Der Status des Service Workers ändert sich in 'installed' und wird dann aktiviert.

Aktivierung

Wenn Registrierung und Installation erfolgreich sind, Der Service Worker wird aktiviert und sein Status ist 'activating' Die Arbeiten können während der Aktivierung im activate-Ereignis. Eine typische Aufgabe in diesem Fall ist das Bereinigen von alten Caches, Für einen neuen Service Worker dies im Moment nicht relevant ist, Wir kommen noch genauer auf die Service Worker-Updates zurück.

Bei neuen Service Workern wird activate sofort ausgelöst, nachdem install erfolgreich war. Sobald die Aktivierung abgeschlossen ist, Der Status des Service Workers wird zu 'activated'. Beachten Sie, dass standardmäßig Der neue Service Worker wird die Seite erst nach der nächsten Navigation oder der nächsten Aktualisierung der Seite steuern.

Service Worker-Updates verarbeiten

Sobald der erste Service Worker bereitgestellt ist, muss er wahrscheinlich später aktualisiert werden. Eine Aktualisierung kann beispielsweise erforderlich sein, wenn Änderungen an der Anfrageverarbeitung oder der Precaching-Logik vorgenommen werden.

Wann Updates erfolgen

Browser suchen in folgenden Fällen nach Updates für einen Service Worker:

So werden Updates durchgeführt

Es ist wichtig, zu wissen, wann der Browser einen Service Worker aktualisiert. aber auch das „Wie“. Wenn die URL oder der Geltungsbereich eines Service Workers unverändert ist, Ein derzeit installierter Service Worker wird nur dann auf eine neue Version aktualisiert, wenn sich der Inhalt geändert hat.

Browser erkennen Änderungen auf unterschiedliche Weise:

  • Alle Byte für Byte-Änderungen an Skripts, die von importScripts, falls zutreffend.
  • Alle Änderungen am Top-Level-Code des Service Workers die den vom Browser generierten Fingerabdruck beeinflusst.

Der Browser hat hier einiges zu tun. Damit der Browser alle notwendigen Funktionen hat, um Änderungen an den Inhalten eines Service Workers zuverlässig zu erkennen, weisen Sie den HTTP-Cache nicht an, ihn zu speichern, und ändern Sie nicht seinen Dateinamen. Der Browser führt automatisch eine Updateüberprüfung durch, wenn eine Navigation zu einer neuen Seite im Bereich eines Service Workers erfolgt.

Updateprüfungen manuell auslösen

Was Aktualisierungen betrifft, sollte sich die Registrierungslogik im Allgemeinen nicht ändern. Eine Ausnahme könnte jedoch sein, wenn Sitzungen auf einer Website langlebig sind. Dies kann bei Single-Page-Anwendungen passieren, Navigationsanfragen selten, da die Anwendung in der Regel zu Beginn ihres Lebenszyklus auf eine Navigationsanforderung stößt. In solchen Fällen kann ein manuelles Update im Hauptthread ausgelöst werden:

navigator.serviceWorker.ready.then((registration) => {
  registration.update();
});

Bei herkömmlichen Websites oder Nutzersitzungen nicht langlebig sind, manuelle Updates auszulösen, ist wahrscheinlich nicht nötig.

Installation

Wenn Sie einen Bundler zum Generieren statischer Inhalte enthalten die Assets Hashes im Namen. wie framework.3defa9d2.js. Angenommen, einige dieser Assets werden vorab für den Offlinezugriff im Cache gespeichert. Dazu wäre ein Service Worker-Update erforderlich, um aktualisierte Assets vorab im Cache zu speichern:

self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v2';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v2'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.ced4aef2.css',
      '/css/home.cbe409ad.css',
      '/js/home.109defa4.js',
      '/js/jquery.38caf32d.js'
    ]);
  }));
});

Im Vergleich zum ersten install-Ereignis von vorhin gibt es zwei Dinge:

  1. Eine neue Cache-Instanz mit dem Schlüssel 'MyFancyCacheName_v2' wird erstellt.
  2. Die Namen der vorab im Cache gespeicherten Assets haben sich geändert.

Zu beachten ist, dass neben dem vorherigen Service Worker ein aktualisierter Service Worker installiert wird. Das bedeutet, dass der alte Service Worker weiterhin alle geöffneten Seiten steuert. wechselt der neue Wartezustand bis zu seiner Aktivierung.

Standardmäßig wird ein neuer Service Worker aktiviert, wenn keine Clients vom alten gesteuert werden. Dies ist der Fall, wenn alle geöffneten Tabs für die entsprechende Website geschlossen sind.

Aktivierung

Wenn ein aktualisierter Service Worker installiert ist und die Wartephase endet, aktiviert und der alte Service Worker verworfen wird. Beim activate-Ereignis eines aktualisierten Service Workers werden häufig alte Caches bereinigt. Entfernen Sie alte Caches, indem Sie die Schlüssel für alle geöffneten Cache-Instanzen mit abrufen. caches.keys Löschen von Caches, die sich nicht auf einer Zulassungsliste befinden, caches.delete:

self.addEventListener('activate', (event) => {
  // Specify allowed cache keys
  const cacheAllowList = ['MyFancyCacheName_v2'];

  // Get all the currently active `Cache` instances.
  event.waitUntil(caches.keys().then((keys) => {
    // Delete all caches that aren't in the allow list:
    return Promise.all(keys.map((key) => {
      if (!cacheAllowList.includes(key)) {
        return caches.delete(key);
      }
    }));
  }));
});

Alte Caches bereinigen sich nicht von selbst. Das müssen wir selbst machen oder riskieren, Speicherkontingente. Da die 'MyFancyCacheName_v1' des ersten Service Workers veraltet ist, wird die Cache-Zulassungsliste aktualisiert, um 'MyFancyCacheName_v2', Dabei werden Caches mit einem anderen Namen gelöscht.

Das activate-Ereignis wird beendet, nachdem der alte Cache entfernt wurde. Jetzt übernimmt der neue Service Worker die Seite, und die alte ersetzen!

Der Lebenszyklus ist endlos

Ob die Workbox für die Bereitstellung und Updates von Service Workern verwendet wird, oder die Service Worker API direkt verwendet wird, Es lohnt sich, den Lebenszyklus des Service Workers zu verstehen. Mit diesem Verständnis sollte das Verhalten der Service Worker logischer als mysteriös erscheinen.

Wenn Sie mehr über dieses Thema erfahren möchten, lohnt es sich, diesem Artikel von Jake Archibald. Der gesamte Prozess rund um den Lebenszyklus des Dienstes ist nuanciert, aber es ist bekannt. Dieses Wissen wird bei der Verwendung von Workbox weitreichende Fähigkeiten bringen.