Wenn Sie Workbox verwenden, möchten Sie möglicherweise eine Anforderung und eine Antwort bearbeiten, während sie abgerufen oder im Cache gespeichert werden. Mit Workbox-Plug-ins können Sie Ihren Service Worker mit minimalem zusätzlichen Codebaustein um zusätzliche Verhaltensweisen erweitern. Sie können gebündelt und in Ihren eigenen Projekten wiederverwendet oder für andere Nutzer veröffentlicht werden.
Workbox bietet eine Reihe vorkonfigurierter Plug-ins. Wenn Sie ein echter Experte sind, können Sie auch benutzerdefinierte Plug-ins schreiben, die auf die Anforderungen Ihrer Anwendung zugeschnitten sind.
Verfügbare Workbox-Plug-ins
Workbox bietet die folgenden offiziellen Plug-ins für die Verwendung in Ihrem Service Worker:
BackgroundSyncPlugin
: Sollte eine Netzwerkanfrage fehlschlagen, können Sie sie mit diesem Plug-in einer Warteschlange für die Synchronisierung im Hintergrund hinzufügen, damit sie beim nächsten Synchronisierungsereignis noch einmal angefordert wird.BroadcastUpdatePlugin
: Ermöglicht Ihnen das Senden einer Nachricht auf einem Broadcast-Channel oder überpostMessage()
, wenn ein Cache aktualisiert wird.CacheableResponsePlugin
: Nur Anfragen im Cache speichern, die bestimmte Kriterien erfüllen.ExpirationPlugin
: Verwaltet die Anzahl und das Höchstalter von Elementen in einem Cache.RangeRequestsPlugin
: Antworten auf Anfragen, die einenRange
-HTTP-Header enthalten.
Workbox-Plug-ins werden mit einer Workbox-Strategie verwendet. Dabei wird der plugins
-Property der Strategie eine Instanz des Plug-ins hinzugefügt:
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
})
);
Methoden für benutzerdefinierte Plug-ins
Ein Workbox-Plug-in muss eine oder mehrere Callback-Funktionen implementieren. Wenn Sie einer Strategie ein Plug-in hinzufügen, werden die Callback-Funktionen automatisch zur richtigen Zeit ausgeführt. Die Strategy (Strategie) übergibt Ihrer Callback-Funktion relevante Informationen über die aktuelle Anfrage und/oder Antwort und gibt dem Plug-in den Kontext, den es für die Aktion benötigt. Die folgenden Callback-Funktionen werden unterstützt:
cacheWillUpdate
: Wird aufgerufen, bevor einResponse
zum Aktualisieren eines Cache verwendet wird. Bei dieser Methode kann die Antwort geändert werden, bevor sie dem Cache hinzugefügt wird. Sie können auchnull
zurückgeben, um eine vollständige Aktualisierung des Caches zu vermeiden.cacheDidUpdate
: Wird aufgerufen, wenn ein neuer Eintrag zu einem Cache hinzugefügt oder ein vorhandener Eintrag aktualisiert wird. Plug-ins, die diese Methode verwenden, können nützlich sein, wenn Sie eine Aktion nach einer Cache-Aktualisierung ausführen möchten.cacheKeyWillBeUsed
: Wird aufgerufen, bevor eine Anfrage als Cache-Schlüssel verwendet wird. Dies gilt sowohl für Cache-Lookups (wennmode
auf'read'
) als auch Cache-Schreibvorgänge (wennmode
auf'write'
gesetzt ist). Dieser Callback ist nützlich, wenn Sie URLs überschreiben oder normalisieren müssen, bevor Sie sie für den Zugriff auf Caches verwenden.cachedResponseWillBeUsed
: Wird aufgerufen, unmittelbar bevor eine Antwort aus einem Cache verwendet wird, sodass Sie diese Antwort untersuchen können. Zu diesem Zeitpunkt können Sie entweder eine andere Antwort odernull
zurückgeben.requestWillFetch
: Wird immer dann aufgerufen, wenn eine Anfrage kurz vor der Übertragung an das Netzwerk steht. Das ist hilfreich, wenn Sie denRequest
kurz vor der Übertragung an das Netzwerk ändern müssen.fetchDidFail
: Wird aufgerufen, wenn eine Netzwerkanfrage fehlschlägt, höchstwahrscheinlich aufgrund fehlender Netzwerkverbindung. Sie wird nicht ausgelöst, wenn der Browser eine Netzwerkverbindung hat, aber einen Fehler empfängt (z. B.404 Not Found
).fetchDidSucceed
: Wird aufgerufen, wenn eine Netzwerkanfrage erfolgreich ist, unabhängig vom HTTP-Antwortcode.handlerWillStart
: Wird aufgerufen, bevor eine Handler-Logik ausgeführt wird. Dies ist nützlich, wenn Sie den anfänglichen Handler-Status festlegen müssen. Wenn Sie beispielsweise wissen möchten, wie lange der Handler für das Generieren einer Antwort gedauert hat, können Sie sich die Startzeit in diesem Callback notieren.handlerWillRespond
: Wird aufgerufen, bevor diehandle()
-Methode der Strategie eine Antwort zurückgibt. Dies ist hilfreich, wenn Sie eine Antwort ändern müssen, bevor sie an eineRouteHandler
oder eine andere benutzerdefinierte Logik zurückgegeben wird.handlerDidRespond
: Wird aufgerufen, nachdem diehandle()
-Methode der Strategie eine Antwort zurückgegeben hat. An dieser Stelle kann es nützlich sein, die abschließenden Antwortdetails aufzuzeichnen (z. B. nach Änderungen, die von anderen Plug-ins vorgenommen wurden).handlerDidComplete
: Wird aufgerufen, nachdem alle Verlängerungsdauer-Versprechen, die durch den Aufruf der Strategie zum Ereignis hinzugefügt wurden, erfolgreich waren. Dies ist hilfreich, wenn Sie einen Bericht zu Daten erstellen müssen, die warten müssen, bis der Handler fertig ist, um Dinge wie Cache-Trefferstatus, Cache-Latenz, Netzwerklatenz und andere nützliche Informationen zu berechnen.handlerDidError
: Wird aufgerufen, wenn der Handler von keiner Quelle eine gültige Antwort liefern kann. Dies ist der optimale Zeitpunkt, um eine Fallback-Antwort als Alternative zum Fehlschlagen bereitzustellen.
Alle diese Callbacks sind async
und erfordern daher die Verwendung von await
, wenn ein Cache- oder Abrufereignis den relevanten Punkt für den betreffenden Callback erreicht.
Wenn ein Plug-in alle oben genannten Callbacks verwendet, wäre der Code so:
const myPlugin = {
cacheWillUpdate: async ({request, response, event, state}) => {
// Return `response`, a different `Response` object, or `null`.
return response;
},
cacheDidUpdate: async ({
cacheName,
request,
oldResponse,
newResponse,
event,
state,
}) => {
// No return expected
// Note: `newResponse.bodyUsed` is `true` when this is called,
// meaning the body has already been read. If you need access to
// the body of the fresh response, use a technique like:
// const freshResponse = await caches.match(request, {cacheName});
},
cacheKeyWillBeUsed: async ({request, mode, params, event, state}) => {
// `request` is the `Request` object that would otherwise be used as the cache key.
// `mode` is either 'read' or 'write'.
// Return either a string, or a `Request` whose `url` property will be used as the cache key.
// Returning the original `request` will make this a no-op.
return request;
},
cachedResponseWillBeUsed: async ({
cacheName,
request,
matchOptions,
cachedResponse,
event,
state,
}) => {
// Return `cachedResponse`, a different `Response` object, or null.
return cachedResponse;
},
requestWillFetch: async ({request, event, state}) => {
// Return `request` or a different `Request` object.
return request;
},
fetchDidFail: async ({originalRequest, request, error, event, state}) => {
// No return expected.
// Note: `originalRequest` is the browser's request, `request` is the
// request after being passed through plugins with
// `requestWillFetch` callbacks, and `error` is the exception that caused
// the underlying `fetch()` to fail.
},
fetchDidSucceed: async ({request, response, event, state}) => {
// Return `response` to use the network response as-is,
// or alternatively create and return a new `Response` object.
return response;
},
handlerWillStart: async ({request, event, state}) => {
// No return expected.
// Can set initial handler state here.
},
handlerWillRespond: async ({request, response, event, state}) => {
// Return `response` or a different `Response` object.
return response;
},
handlerDidRespond: async ({request, response, event, state}) => {
// No return expected.
// Can record final response details here.
},
handlerDidComplete: async ({request, response, error, event, state}) => {
// No return expected.
// Can report any data here.
},
handlerDidError: async ({request, event, error, state}) => {
// Return a `Response` to use as a fallback, or `null`.
return fallbackResponse;
},
};
Das in den oben aufgeführten Rückrufen verfügbare Objekt event
ist das ursprüngliche Ereignis, das die Abruf- oder Cache-Aktion ausgelöst hat. Manchmal gibt es kein ursprüngliches Ereignis. Daher sollte der Code prüfen, ob es vorhanden ist, bevor er darauf verweist.
Allen Plug-in-Callbacks wird außerdem ein state
-Objekt übergeben, das für ein bestimmtes Plug-in und die aufgerufene Strategie eindeutig ist. Das bedeutet, dass Sie Plug-ins schreiben können, mit denen ein Callback basierend auf der Aktivität eines anderen Callbacks im selben Plug-in eine Aufgabe bedingt ausführen kann. Sie können z. B. die Differenz zwischen der Ausführung von requestWillFetch()
und fetchDidSucceed()
oder fetchDidFail()
berechnen.
Plug-ins von Drittanbietern
Wenn Sie ein Plug-in entwickeln und glauben, dass es außerhalb Ihres Projekts verwendet wird, empfehlen wir Ihnen, es als Modul zu veröffentlichen. Nachfolgend finden Sie eine kurze Liste der Workbox-Plug-ins, die von der Community bereitgestellt werden:
cloudinary-workbox-plugin
, wodurch Anfragen für von Cloudinary gehostete Bilder anhand der aktuellen Verbindungsgeschwindigkeit dynamisch umgeschrieben werden.- Mit
workbox-plugin-firebase-auth
können SieAuthorization: Bearer
für ausgehende Anfragen verwalten, für die eine Firebase-Authentifizierung erforderlich ist.
Sie können möglicherweise weitere Workbox-Plug-ins von der Community finden, indem Sie im Repository von npm suchen.
Wenn Sie schließlich ein Workbox-Plug-in erstellt haben, das Sie freigeben möchten, fügen Sie bei der Veröffentlichung das Keyword workbox-plugin
hinzu. Teilen Sie uns dies bitte auf Twitter mit @WorkboxJS mit.