Passer de Workbox v4 à la version 5

Ce guide présente les modifications destructives introduites dans Workbox v5 et fournit des exemples de modifications à apporter pour effectuer la mise à niveau depuis Workbox v4.

Modifications majeures

Classes de plug-in renommées

Un certain nombre de packages Workbox v4 incluaient des classes nommées Plugin. Dans la version 5, ces classes ont été renommées pour suivre le format identifiant du package + Plugin :

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

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

Point de remplacement du fichier manifeste de préchargement par défaut

Auparavant, lorsque vous utilisiez l'un des outils de compilation en mode "injecter le fichier manifeste", la présence de precacheAndRoute([]) était vérifiée dans votre fichier source du service worker, et le tableau vide [] était utilisé comme espace réservé pour le point d'injection du fichier manifeste de préchargement.

Dans Workbox v5, la logique de remplacement a changé. 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 ce changement offre une expérience plus simple, tout en permettant aux développeurs de mieux contrôler la façon dont le fichier manifeste injecté est utilisé dans le code d'un service worker personnalisé. Si nécessaire, vous pouvez modifier cette chaîne de remplacement via l'option de configuration injectionPoint.

Deux options auparavant prises en charge pour les itinéraires de navigation, blacklist et whitelist, ont été renommées denylist et allowlist.

workbox-routing était auparavant compatible avec une méthode, registerNavigationRoute(), qui, en interne, effectuait deux actions :

  1. Détecté si un événement fetch donné avait un mode de 'navigate'.
  2. Si c'est le cas, la requête a été traitée à l'aide du contenu d'une URL codée en dur précédemment mise en cache, quelle que soit l'URL vers laquelle l'utilisateur a accédé.

Il s'agit d'un modèle couramment utilisé lors de l'implémentation de l'architecture de shell d'application.

La deuxième étape, qui consiste à générer une réponse en lisant le cache, n'entre pas dans les responsabilités de workbox-routing. Nous la considérons plutôt comme 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 la section "Generate SW" (Générer un logiciel) de l'outil de compilation le basculement s'effectue automatiquement. Si vous avez déjà configuré les options navigateFallbackBlacklist ou navigateFallbackWhitelist, remplacez-les respectivement par navigateFallbackDenylist ou navigateFallbackAllowlist.

Si vous utilisez le mode "inject manifest" ou si vous écrivez simplement le service worker vous-même, et que votre service worker Workbox v4 appelle directement registerNavigationRoute(), vous devrez modifier votre code pour obtenir un 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.

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

Appeler makeRequest() équivaut principalement à appeler handle() sur l'une des classes workbox-strategy. Les différences entre les deux méthodes étaient si légères qu'il n'était pas logique de les conserver toutes les deux. 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 n'utilise pas event.request par défaut. Veillez à 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 lorsque cette fonction était prise en charge, et reviendrait à utiliser postMessage() uniquement lorsque Broadcast Channel n'était pas pris en charge.

Nous avons réalisé que le fait d'avoir à écouter 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é. Il n'y a pas de mise en mémoire tampon avec l'API Broadcast Channel, et les messages diffusés sont simplement supprimés s'ils sont envoyés avant qu'une page cliente ne soit prête à les recevoir.

C'est pourquoi nous avons modifié workbox-broadcast-update pour qu'il utilise toujours postMessage() dans la version 5. Les messages sont envoyés un par un à toutes les pages client du champ d'application du service worker actuel.

Pour vous adapter à ce nouveau comportement, vous pouvez supprimer tout code présent dans les pages client ayant créé des instances BroadcastChannel et configurer à la place 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 n'ont pas 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 une version ultérieure

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

Workbox-webpack-plugin Nécessite webpack v4 ou une version ultérieure

Si vous utilisez workbox-webpack-plugin, mettez à jour votre configuration webpack pour qu'elle utilise au moins Webpack v4.

Refonte des options de l'outil de compilation

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 un bundle d'exécution Workbox local pour vous. L'option importWorkboxFrom n'a donc plus de sens.

Consultez la documentation de l'outil concerné pour obtenir la liste des options compatibles.

Suppression de generateSWString de workbox-build

Le mode generateSWString a été supprimé de workbox-build. L'impact devrait être minime, car cette fonctionnalité était principalement utilisée en interne par workbox-webpack-plugin.

Modifications facultatives

Utiliser des importations de modules

Bien que cette modification soit a) facultative et b) techniquement possible lorsque vous utilisez 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) pour "générer un logiciel" , ce changement s'applique automatiquement. Tous ces outils génèrent un bundle local et personnalisé de l'environnement d'exécution Workbox, accompagné du code réel nécessaire à l'implémentation de votre logique de service worker. Dans ce scénario, il n'y a plus de dépendance envers workbox-sw ni envers la copie du CDN de Workbox. En fonction de la valeur de votre configuration inlineWorkboxRuntime, l'environnement d'exécution Workbox sera divisé en un fichier distinct qui devra être déployé avec votre service worker (si la valeur est définie sur false, qui est la valeur par défaut) ou inclus dans la logique du service worker (lorsqu'il est défini sur true).

Si vous utilisez les outils de compilation dans la section "Injecter un fichier manifeste" ou si vous n'utilisez pas du tout les outils de compilation de Workbox, vous pouvez découvrir comment créer votre propre bundle d'environnement d'exécution Workbox dans le guide Utiliser des bundles (webpack/Rollup) avec Workbox.

La documentation et les exemples pour la version 5 sont écrits en supposant que le module importe la syntaxe. Toutefois, l'espace de noms workbox.* continuera d'être compatible avec Workbox v5.

Lire les réponses en pré-cache

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

Pour simplifier ce processus, workbox-precaching dans la version 5 prend en charge 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 de TypeScript

Dans la version 5, les bibliothèques d'exécution Workbox sont écrites en TypeScript. Nous continuerons de publier des modules et des bundles JavaScript transcompilés pour les 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 toujours à jour directement à partir du projet Workbox.

Exemple de migration

Ce commit illustre une migration assez complexe, avec un commentaire intégré. Il utilise Rollup pour inclure un environnement d'exécution Workbox 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 les étapes avant et après de la mise à niveau d'un fichier de service worker de la version 4 à la version v5, avec un passage à TypeScript.

Obtenir de l'aide

La plupart des migrations devraient être simples. Si vous rencontrez des problèmes qui ne sont pas abordés dans ce guide, signalez-les sur GitHub.