Von Workbox v4 zu v5 migrieren

Dieser Leitfaden konzentriert sich auf funktionsgefährdende Änderungen in Workbox v5 und enthält Beispiele dafür, welche Änderungen Sie bei einem Upgrade von Workbox v4 vornehmen müssen.

Nicht abwärtskompatible Änderungen

Plug-in-Klassen umbenannt

Eine Reihe von Workbox v4-Paketen enthielt Klassen mit dem Namen Plugin. In Version 5 wurden diese Klassen umbenannt, um dem Muster der Paketkennung + Plugin zu folgen:

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

Diese Umbenennung gilt unabhängig davon, ob Sie die Klassen über Modulimporte oder über die workbox.*-Namespaces verwenden.

Punkt zum Ersetzen des Standard-Precache-Manifests

Bisher wurde bei Verwendung eines der Build-Tools im Modus „Manifest einfügen“ in der Quell-Service-Worker-Datei das Vorhandensein von precacheAndRoute([]) überprüft. Dabei wurde das leere Array [] als Platzhalter für den Punkt verwendet, an dem das Precache-Manifest eingeschleust wurde.

In Workbox v5 hat sich die Ersetzungslogik geändert, sodass self.__WB_MANIFEST jetzt standardmäßig als Injection-Point verwendet wird.

// v4:
precacheAndRoute([]);

// v5:
precacheAndRoute(self.__WB_MANIFEST);

Wie in dieser Diskussion beschrieben, sind wir der Meinung, dass diese Änderung die Nutzerfreundlichkeit vereinfacht und Entwicklern gleichzeitig mehr Kontrolle darüber gibt, wie das eingefügte Manifest innerhalb des benutzerdefinierten Service Worker-Codes verwendet wird. Bei Bedarf können Sie diesen Ersatzstring über die Konfigurationsoption injectionPoint ändern.

Die beiden Optionen blacklist und whitelist, die zuvor für Navigationsrouten unterstützt wurden, wurden in denylist und allowlist umbenannt.

workbox-routing unterstützte zuvor die Methode registerNavigationRoute(), die im Hintergrund zwei Dinge erledigt hat:

  1. Ermittelt, ob ein bestimmtes fetch-Ereignis einen mode von 'navigate' hatte.
  2. Wenn ja, wurde auf diese Anfrage mit dem Inhalt einer zuvor im Cache gespeicherten, hartcodierten URL geantwortet, unabhängig von der URL, zu der navigiert wurde.

Dies ist ein gängiges Muster bei der Implementierung der App Shell-Architektur.

Der zweite Schritt, das Generieren einer Antwort durch Auslesen aus dem Cache, liegt außerhalb der Verantwortung von workbox-routing. Stattdessen sehen wir sie als Funktion, die Teil von workbox-precaching über die neue Methode createHandlerBoundToURL() sein sollte. Diese neue Methode kann in enger Abstimmung mit der vorhandenen NavigationRoute-Klasse in workbox-routing verwendet werden, um dieselbe Logik zu erzielen.

Wenn Sie die Option navigateFallback im Modus „Software generieren“ des Build-Tools verwenden, erfolgt der Wechsel automatisch. Wenn Sie zuvor die Optionen navigateFallbackBlacklist oder navigateFallbackWhitelist konfiguriert haben, ändern Sie diese zu navigateFallbackDenylist bzw. navigateFallbackAllowlist.

Wenn Sie den Modus "Manifest einfügen" verwenden oder den Service Worker selbst schreiben und Ihr Service Worker der Workbox v4 direkt registerNavigationRoute() aufruft, müssen Sie eine Änderung an Ihrem Code vornehmen, um das entsprechende Verhalten zu erhalten.

// v4:
import {getCacheKeyForURL} from 'workbox-precaching';
import {registerNavigationRoute} from 'workbox-routing';

const appShellCacheKey = getCacheKeyForURL('/app-shell.html');
registerNavigationRoute(appShellCacheKey, {
  whitelist: [...],
  blacklist: [...],
});

// v5:
import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';

const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
  allowlist: [...],
  denylist: [...],
});
registerRoute(navigationRoute);

Du musst getCacheKeyForURL() nicht mehr anrufen, da createHandlerBoundToURL() das für dich übernimmt.

makeRequest() aus den workbox-strategien entfernt

Der Aufruf von makeRequest() entspricht größtenteils dem Aufruf von handle() für eine der workbox-strategy-Klassen. Die Unterschiede zwischen den beiden Methoden waren so gering, dass es nicht sinnvoll war, beide in der Nähe zu halten. Entwickler, die makeRequest() angerufen haben, sollten ohne weitere Änderungen zur Verwendung von handle() wechseln können:

// v4:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.makeRequest({event, request});

// v5:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.handle({event, request});

In Version 5 behandelt handle() request als erforderlichen Parameter und greift nicht auf die Verwendung von event.request zurück. Achten Sie darauf, beim Aufrufen von handle() eine gültige Anfrage zu übergeben.

workbox-broadcast-update verwendet immer postMessage()

In Version 4 verwendet die workbox-broadcast-update-Bibliothek standardmäßig die Broadcast Channel API zum Senden von Nachrichten, wenn dies unterstützt wird. postMessage() wird nur verwendet, wenn Broadcast Channel nicht unterstützt wird.

Uns wurde klar, dass das Schreiben von clientseitigem Code zu kompliziert wurde, weil wir auf zwei potenzielle Quellen eingehender Nachrichten warten mussten. Außerdem werden bei einigen Browsern postMessage()-Aufrufe vom Service Worker, die an Clientseiten gesendet werden, automatisch zwischengespeichert, bis ein message-Event-Listener eingerichtet wurde. Es erfolgt keine Zwischenspeicherung mit der Broadcast Channel API und übertragene Nachrichten werden einfach verworfen, wenn sie gesendet werden, bevor eine Clientseite für den Empfang bereit ist.

Aus diesem Grund haben wir workbox-broadcast-update so geändert, dass in Version 5 immer postMessage() verwendet wird. Nachrichten werden nacheinander an alle Clientseiten im Bereich des aktuellen Service Workers gesendet.

Um diesem neuen Verhalten Rechnung zu tragen, können Sie jeglichen Code von Clientseiten entfernen, die BroadcastChannel-Instanzen erstellt haben, und stattdessen einen message-Event-Listener für navigator.serviceWorker einrichten:

// v4:
const updatesChannel = new BroadcastChannel('api-updates');
updatesChannel.addEventListener('message', event => {
  const {cacheName, updatedUrl} = event.data.payload;
  // ... your code here ...
});

// v5:
// This listener should be added as early as possible in your page's lifespan
// to ensure that messages are properly buffered.
navigator.serviceWorker.addEventListener('message', event => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;
    // ... your code here ...
  }
});

workbox-window-Nutzer sollten keine Änderungen vornehmen müssen, da die interne Logik aktualisiert wurde, um postMessage()-Aufrufe zu erfassen.

Build-Tools erfordern Node.js v8 oder höher

Node.js-Versionen vor V8 werden für workbox-webpack-plugin, workbox-build oder workbox-cli nicht mehr unterstützt. Wenn Sie eine ältere Node.js-Version als 8 verwenden, aktualisieren Sie die Laufzeit auf eine unterstützte Version.

workbox-webpack-plugin erfordert Webpack Version 4 oder höher

Wenn du workbox-webpack-plugin verwendest, aktualisiere deine Webpack-Einrichtung, um mindestens Webpack Version 4 zu verwenden.

Überarbeitung der Build-Tool-Optionen

Einige workbox-build-, workbox-cli- und workbox-webpack-plugin-Konfigurationsparameter werden nicht mehr unterstützt. generateSW erstellt beispielsweise immer ein lokales Workbox-Laufzeit-Bundle für Sie, sodass die Option importWorkboxFrom nicht mehr sinnvoll ist.

Eine Liste der unterstützten Optionen finden Sie in der Dokumentation des jeweiligen Tools.

"generateSWString" aus "workbox-build" entfernt

Der Modus generateSWString wurde aus workbox-build entfernt. Wir gehen davon aus, dass dies nur minimale Auswirkungen haben wird, da es hauptsächlich intern von workbox-webpack-plugin verwendet wurde.

Optionale Änderungen

Modulimporte verwenden

Diese Änderung ist bei Verwendung von Workbox v4 a) optional und b) technisch möglich. Die größte Änderung, die wir beim Wechsel zu v5 erwarten, ist jedoch ein Modell, bei dem Sie Ihren eigenen gebündelten Service Worker erstellen, indem Sie Workbox-Module importieren. Dieser Ansatz ist eine Alternative, um importScripts('/path/to/workbox-sw.js') oben im Service Worker aufzurufen und Workbox über den Namespace workbox.* zu verwenden.

Wenn du eines der Build-Tools (workbox-webpack-plugin, workbox-build, workbox-cli) im Modus „SW generieren“ verwendest, wird diese Änderung automatisch vorgenommen. Alle diese Tools geben ein lokales, benutzerdefiniertes Bundle der Workbox-Laufzeit zusammen mit dem tatsächlichen Code aus, der für die Implementierung Ihrer Service Worker-Logik erforderlich ist. In diesem Szenario besteht keine Abhängigkeit mehr von workbox-sw oder der CDN-Kopie von Workbox. Abhängig vom Wert Ihrer inlineWorkboxRuntime-Konfiguration wird die Workbox-Laufzeit entweder in eine separate Datei aufgeteilt, die zusammen mit Ihrem Service Worker bereitgestellt wird (wenn false (Standardeinstellung) festgelegt ist), oder inline in die Service-Worker-Logik eingefügt (wenn true festgelegt ist).

Wenn Sie die Build-Tools im Modus „Manifest einfügen“ oder überhaupt nicht die Build-Tools von Workbox verwenden, finden Sie weitere Informationen zum Erstellen Ihres eigenen Workbox-Laufzeit-Bundles in der Anleitung Bundlers (Webpack/Rollup) mit Workbox verwenden.

Die Dokumentation und Beispiele für v5 basieren auf der Syntax der Modulimporte. Der workbox.*-Namespace wird jedoch in Workbox v5 weiterhin unterstützt.

Vorab im Cache gespeicherte Antworten lesen

Einige Entwickler müssen vorab im Cache gespeicherte Antworten direkt aus dem Cache lesen, anstatt sie implizit über die Methode precacheAndRoute() zu verwenden. Ein gängiges Muster in v4 besteht darin, zuerst den für die aktuelle Version einer vorab im Cache gespeicherten Ressource spezifischen Cache-Schlüssel abzurufen und diesen Schlüssel dann zusammen mit dem Cache-Namen des Precaches an caches.match() zu übergeben, um den Response abzurufen.

Um diesen Vorgang zu vereinfachen, unterstützt workbox-precaching in Version 5 die neue, äquivalente Methode matchPrecache():

// v4:
import {cacheNames} from 'workbox-core';
import {getCacheKeyForURL} from 'workbox-precaching';

const cachedResponse = await caches.match(
  getCacheKeyForURL(`/somethingPrecached`),
  {
    cacheName: cacheNames.precache,
  }
);

// v5:
import {matchPrecache} from 'workbox-precaching';

const cachedResponse = await matchPrecache(`/somethingPrecached`);

TypeScript-Akzeptanz

In Version 5 werden die Workbox-Laufzeitbibliotheken in TypeScript geschrieben. Wir werden weiterhin transpilierte JavaScript-Module und -Bundles für Entwickler veröffentlichen, die TypeScript nicht übernommen haben. Wenn Sie TypeScript verwenden, sollten Sie jedoch von genauen und immer aktuellen Typinformationen direkt aus dem Workbox-Projekt profitieren.

Beispielmigration

Dieses Commit zeigt, dass die Migration recht kompliziert ist und es Inline-Kommentare gibt. Dabei wird mithilfe von Rollup eine benutzerdefinierte Workbox-Laufzeit in den endgültigen Service Worker aufgenommen, anstatt die Laufzeit aus dem CDN zu laden.

Es werden zwar nicht alle funktionsgefährdenden Änderungen behandelt, aber hier finden Sie Informationen vor und nach dem Upgrade einer Service Worker-Datei von Version 4 auf Version 5, einschließlich eines Wechsels zu TypeScript.

Hilfe erhalten

Wir gehen davon aus, dass die meisten Migrationen unkompliziert sein werden. Wenn Probleme auftreten, die in diesem Leitfaden nicht behandelt werden, eröffnen Sie ein Problem auf GitHub.