Passer de Workbox v4 à la version 5

Ce guide est axé sur les modifications destructives introduites dans Workbox v5 et fournit des exemples de modifications à effectuer avant la mise à niveau depuis Workbox v4.

Modifications majeures

Renommage des classes de plug-ins

Plusieurs packages Workbox v4 incluaient des classes nommées Plugin. Dans la version 5, ces classes ont été renommées pour suivre l'identifiant de package de motif + Plugin:

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

Ce changement de nom s'applique que vous utilisiez les classes via des importations de modules ou les espaces de noms workbox.*.

Point de remplacement du fichier manifeste de mise en cache par défaut

Auparavant, lorsque vous utilisiez l'un des outils de compilation en mode "Injecter un fichier manifeste", votre fichier de nœud de calcul de service source était vérifié pour détecter la présence de precacheAndRoute([]), avec le tableau vide [] utilisé comme espace réservé pour le point où le fichier manifeste de mise en cache avait été injecté.

Dans Workbox v5, la logique de remplacement a changé et self.__WB_MANIFEST est désormais utilisé par défaut comme point d'injection.

// v4:
precacheAndRoute([]);

// v5:
precacheAndRoute(self.__WB_MANIFEST);

Comme indiqué dans cette discussion, nous pensons que cette modification simplifie l'expérience, tout en donnant aux développeurs plus de contrôle sur l'utilisation du fichier manifeste injecté dans le code de service worker personnalisé. Si nécessaire, vous pouvez modifier cette chaîne de remplacement via l'option de configuration injectionPoint.

Deux options qui étaient auparavant compatibles avec les itinéraires de navigation, blacklist et whitelist, ont été renommées denylist et allowlist.

workbox-routing prenait auparavant en charge une méthode registerNavigationRoute() qui, en arrière-plan, effectuait deux opérations:

  1. Détecté si un événement fetch donné présentait une mode de 'navigate'.
  2. Si tel est le cas, il répond à cette requête à l'aide du contenu d'une URL précédemment mise en cache et codée en dur, quelle que soit l'URL consultée.

Il s'agit d'un modèle courant à utiliser lors de l'implémentation de l'architecture App Shell.

La deuxième étape, qui consiste à générer une réponse via la lecture du cache, n'entre pas dans le cadre de ce que nous considérons comme étant workbox-routing. Il s'agit plutôt d'une fonctionnalité qui devrait faire partie de workbox-precaching, via une nouvelle méthode, createHandlerBoundToURL(). Cette nouvelle méthode peut fonctionner conjointement avec la classe NavigationRoute existante dans workbox-routing pour accomplir la même logique.

Si vous utilisez l'option navigateFallback dans l'un des modes "generate SW" de l'outil de compilation, le basculement est automatique. Si vous avez déjà configuré les options navigateFallbackBlacklist ou navigateFallbackWhitelist, remplacez-les respectivement par navigateFallbackDenylist ou navigateFallbackAllowlist.

Si vous utilisez le mode "Injecter un fichier manifeste" ou écrivez simplement le service worker vous-même et que votre service worker de la version 4 de Workbox appelle directement registerNavigationRoute(), vous devez modifier votre code pour obtenir le comportement équivalent.

// 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);

Vous n'avez plus besoin d'appeler getCacheKeyForURL(), car createHandlerBoundToURL() s'en charge pour vous.

Suppression de makeRequest() des stratégies de boîte de travail

Appeler makeRequest() revient principalement à appeler handle() sur l'une des classes workbox-strategy. Les différences entre les deux méthodes étaient si légères que les conserver toutes les deux n'avait aucun sens. Les développeurs qui ont appelé makeRequest() devraient pouvoir passer à handle() sans autre modification:

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

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

Dans la version 5, handle() considère request comme un paramètre obligatoire et ne revient pas à utiliser event.request. Assurez-vous de transmettre une requête valide lorsque vous appelez handle().

workbox-broadcast-update utilise toujours postMessage()

Dans la version 4, la bibliothèque workbox-broadcast-update utilisait par défaut l'API Broadcast Channel pour envoyer des messages si elle était compatible, et utilisait postMessage() uniquement lorsque Broadcast Channel n'était pas compatible.

Nous avons réalisé que l'écoute de deux sources potentielles de messages entrants rendait l'écriture du code côté client trop compliquée. De plus, sur certains navigateurs, les appels postMessage() du service worker envoyés aux pages client sont automatiquement mis en mémoire tampon jusqu'à ce qu'un écouteur d'événements message soit configuré. L'API Broadcast Channel ne fait pas l'objet d'une mise en mémoire tampon. Les messages diffusés sont simplement supprimés s'ils sont envoyés avant qu'une page client soit prête à les recevoir.

Pour ces raisons, nous avons modifié workbox-broadcast-update pour toujours utiliser postMessage() dans la version 5. Les messages sont envoyés un par un à toutes les pages client couvertes par le service worker actuel.

Pour vous adapter à ce nouveau comportement, vous pouvez supprimer tout le code présent dans les pages clientes qui créaient des instances BroadcastChannel, puis configurer un écouteur d'événements message sur navigator.serviceWorker:

// 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 ...
  }
});

Les utilisateurs de workbox-window ne devraient pas avoir besoin d'apporter de modifications, car sa logique interne a été mise à jour pour écouter les appels postMessage().

Les outils de compilation nécessitent Node.js v8 ou version ultérieure

Les versions de Node.js antérieures à la v8 ne sont plus compatibles avec workbox-webpack-plugin, workbox-build et workbox-cli. Si vous exécutez une version de Node.js antérieure à la version 8, mettez à jour votre environnement d'exécution vers une version compatible.

workbox-webpack-plugin Nécessite webpack v4 ou version ultérieure

Si vous utilisez workbox-webpack-plugin, mettez à jour la configuration de votre pack Web de façon à utiliser au moins la version 4.

Refonte des options de l'outil de création

Un certain nombre de paramètres de configuration workbox-build, workbox-cli et workbox-webpack-plugin ne sont plus acceptés. Par exemple, generateSW crée toujours pour vous un bundle d'exécution local de la boîte de travail. L'option importWorkboxFrom n'est donc plus pertinente.

Consultez la documentation de l'outil concerné pour obtenir la liste des options prises en charge.

Suppression de generateSWString de workbox-build

Le mode generateSWString a été supprimé de workbox-build. Cette fonctionnalité devrait avoir un impact minime, car elle a été principalement utilisée en interne par workbox-webpack-plugin.

Modifications facultatives

Utiliser les importations de modules

Bien que ce changement soit a) facultatif et b) était techniquement possible lors de l'utilisation de Workbox v4, le plus grand changement que nous prévoyons lors du passage à la version 5 est un modèle dans lequel vous créez votre propre service worker groupé en important les modules de Workbox. Cette approche est une alternative à l'appel de importScripts('/path/to/workbox-sw.js') en haut de votre service worker et à l'utilisation de Workbox via l'espace de noms workbox.*.

Si vous utilisez l'un des outils de compilation (workbox-webpack-plugin, workbox-build, workbox-cli) en mode "Générer un logiciel", cette modification s'appliquera automatiquement. Tous ces outils génèrent un bundle local et personnalisé de l'environnement d'exécution Workbox, ainsi que le code nécessaire à l'implémentation de la logique du service worker. Dans ce scénario, il n'y a plus de dépendance à workbox-sw ni à la copie CDN de Workbox. En fonction de la valeur de votre configuration inlineWorkboxRuntime, l'environnement d'exécution de Workbox sera soit divisé en un fichier distinct qui doit être déployé avec votre service worker (avec la valeur par défaut false), soit intégré à la logique du service worker (lorsqu'il est défini sur true).

Si vous utilisez les outils de compilation en mode "Injecter un fichier manifeste" ou si vous n'utilisez pas du tout les outils de compilation de Workbox, vous pouvez en savoir plus sur la création de votre propre bundle d'exécution Workbox dans le guide Utiliser Bundlers (webpack/Rollup) avec Workbox.

La documentation et les exemples pour la version 5 sont rédigés en partant du principe que la syntaxe d'importation du module est utilisée. Toutefois, l'espace de noms workbox.* restera compatible avec la version 5 de Workbox.

Lire les réponses en cache

Certains développeurs doivent lire les réponses en pré-cache directement à partir du cache, au lieu de les utiliser implicitement via la méthode precacheAndRoute(). Dans la version 4, un modèle courant consiste à obtenir d'abord la clé de cache spécifique à la version actuelle d'une ressource mise en pré-cache, puis à transmettre cette clé avec le nom de cache du pré-cache à caches.match() pour obtenir l'élément Response.

Pour simplifier ce processus, workbox-precaching dans la version 5 accepte une nouvelle méthode équivalente, 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`);

Adoption TypeScript

Dans la version 5, les bibliothèques d'exécution Workbox sont écrites en TypeScript. Nous continuerons à publier des modules et des bundles JavaScript transpilés pour répondre aux besoins des développeurs qui n'ont pas adopté TypeScript. Toutefois, si vous utilisez TypeScript, vous devriez bénéficier d'informations de type précises et à jour, directement depuis le projet Workbox.

Exemple de migration

Ce commit illustre une migration assez complexe, avec des commentaires intégrés. Elle utilise la propriété de consolidation pour inclure un environnement d'exécution de boîte de travail personnalisé dans le service worker final au lieu de charger l'environnement d'exécution à partir du CDN.

Bien qu'il ne couvre pas toutes les modifications destructives, voici l'avant et l'après de la mise à niveau d'un fichier de service worker de la version 4 à la version 5, y compris un passage à TypeScript.

Obtenir de l'aide

Nous estimons que la plupart des migrations seront simples. Si vous rencontrez des problèmes qui ne sont pas abordés dans ce guide, n'hésitez pas à nous le signaler sur GitHub.