Eseguire la migrazione da Workbox v4 a v5

Questa guida si concentra sulle modifiche che provocano un errore introdotte in Workbox v5, con esempi delle modifiche che dovrebbero essere apportate quando esegui l'upgrade da Workbox v4.

Modifiche che provocano un errore

Classi di plug-in rinominate

Diversi pacchetti Workbox v4 includevano classi denominate Plugin. Nella v5, queste classi sono state rinominate in modo da seguire l'identificatore del pacchetto di pattern + Plugin:

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

Questa ridenominazione si applica sia che tu stia utilizzando le classi tramite importazioni di moduli o tramite gli spazi dei nomi workbox.*.

Punto di sostituzione del manifest di pre-cache predefinito

In precedenza, quando utilizzavi uno degli strumenti di creazione in modalità "inject manifest", nel file del service worker di origine veniva controllata la presenza di precacheAndRoute([]), con l'array vuoto [] utilizzato come segnaposto per il punto in cui era stato inserito il manifest di pre-cache.

In Workbox v5, la logica di sostituzione è cambiata e ora self.__WB_MANIFEST viene utilizzato per impostazione predefinita come punto di inserimento.

// v4:
precacheAndRoute([]);

// v5:
precacheAndRoute(self.__WB_MANIFEST);

Come descritto in questa discussione, riteniamo che questa modifica offra un'esperienza più semplice, offrendo contemporaneamente agli sviluppatori un maggiore controllo sul modo in cui il manifest inserito viene utilizzato all'interno del codice del service worker personalizzato. Se necessario, puoi modificare questa stringa sostitutiva tramite l'opzione di configurazione injectionPoint.

Due opzioni che in precedenza erano supportate per i percorsi di navigazione, blacklist e whitelist, sono state rinominate denylist e allowlist.

In passato workbox-routing supportava un metodo, registerNavigationRoute(), che, in background, ha consentito di svolgere due operazioni:

  1. Rilevato se un determinato evento fetch ha avuto mode di 'navigate'.
  2. Se sì, ha risposto alla richiesta utilizzando i contenuti di un URL hardcoded precedentemente memorizzato nella cache, indipendentemente dall'URL di destinazione.

Questo è un pattern comune da utilizzare durante l'implementazione dell'architettura della shell dell'app.

Il secondo passaggio, la generazione di una risposta tramite la lettura dalla cache, non rientra nelle responsabilità di workbox-routing. Consideriamo invece una funzionalità che dovrebbe far parte di workbox-precaching, tramite un nuovo metodo, createHandlerBoundToURL(). Questo nuovo metodo può funzionare insieme alla classe NavigationRoute esistente in workbox-routing per eseguire la stessa logica.

Se utilizzi l'opzione navigateFallback in una delle modalità "Genera software" dello strumento di creazione, il passaggio avverrà automaticamente. Se in precedenza hai configurato le opzioni navigateFallbackBlacklist o navigateFallbackWhitelist, modificale rispettivamente in navigateFallbackDenylist o navigateFallbackAllowlist.

Se utilizzi la modalità "Inject Manifest" o stai semplicemente scrivendo il service worker e il service worker Workbox v4 chiama direttamente registerNavigationRoute(), dovrai apportare una modifica al codice per ottenere il comportamento equivalente.

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

Non devi più chiamare getCacheKeyForURL() perché si occuperà per te di createHandlerBoundToURL().

Rimozione di makeRequest() dalle strategie di workbox

Chiamare makeRequest() equivale principalmente a chiamare handle() in uno dei corsi workbox-strategy. Le differenze tra i due metodi erano talmente lievi che tenerle entrambe non aveva senso. Gli sviluppatori che hanno chiamato makeRequest() dovrebbero poter passare all'utilizzo di handle() senza ulteriori modifiche:

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

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

Nella versione 5, handle() tratta request come parametro obbligatorio e non ricorrerà all'utilizzo di event.request. Assicurati di trasmettere una richiesta valida quando chiami handle().

workbox-broadcast-update Usa sempre postMessage()

Nella versione 4, la libreria workbox-broadcast-update utilizzava per impostazione predefinita l'API Broadcast Channel per l'invio di messaggi quando era supportata e ricorreva a postMessage() solo quando il canale di trasmissione non era supportato.

Ci siamo resi conto che dover ascoltare due potenziali origini dei messaggi in arrivo rendeva la scrittura di codice lato client eccessivamente complicata. Inoltre, su alcuni browser, le chiamate postMessage() dal service worker inviate alle pagine client vengono automaticamente memorizzate nel buffer finché non viene configurato un listener di eventi message. Non viene eseguito il buffering con l'API Broadcast Channel e i messaggi trasmessi vengono eliminati se inviati prima che una pagina client sia pronta a riceverli.

Per questo motivo, abbiamo modificato workbox-broadcast-update in modo che utilizzi sempre postMessage() nella v5. I messaggi vengono inviati uno alla volta a tutte le pagine del client che rientrano nell'ambito del service worker attuale.

Per adeguarti a questo nuovo comportamento, puoi rimuovere qualsiasi codice presente nelle pagine del client che hanno creato BroadcastChannel istanze e, invece, impostare un listener di eventi message su 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 ...
  }
});

Gli utenti di workbox-window non devono apportare alcuna modifica perché la logica interna è stata aggiornata per rimanere in ascolto delle chiamate postMessage().

Gli strumenti di build richiedono Node.js v8 o versioni successive

Le versioni Node.js precedenti alla v8 non sono più supportate per workbox-webpack-plugin, workbox-build o workbox-cli. Se esegui una versione Node.js precedente alla 8, aggiorna il runtime a una versione supportata.

workbox-webpack-plugin Richiede webpack v4 o versione successiva

Se utilizzi workbox-webpack-plugin, aggiorna la configurazione del webpack per utilizzare almeno webpack v4.

Revisione delle opzioni dello strumento di creazione

Alcuni parametri di configurazione workbox-build, workbox-cli e workbox-webpack-plugin non sono più supportati. Ad esempio, generateSW creerà sempre un bundle runtime Workbox locale per te, quindi l'opzione importWorkboxFrom non ha più senso.

Consulta la documentazione dello strumento pertinente per gli elenchi delle opzioni supportate.

Rimozione di generateSWString da workbox-build

La modalità generateSWString è stata rimossa da workbox-build. Ci aspettiamo che l'impatto sia minimo, in quanto è stato utilizzato principalmente internamente da workbox-webpack-plugin.

Modifiche facoltative

Utilizzo delle importazioni dei moduli

Anche se questa modifica è a) facoltativa e b) tecnicamente è stata possibile quando si utilizza Workbox v4, il cambiamento più grande che anticipiamo durante il passaggio alla v5 è un modello in cui puoi creare il tuo service worker in bundle importando i moduli di Workbox. Questo approccio è un'alternativa alla chiamata di importScripts('/path/to/workbox-sw.js') nella parte superiore del service worker e all'utilizzo di Workbox tramite lo spazio dei nomi workbox.*.

Se utilizzi uno degli strumenti di creazione (workbox-webpack-plugin, workbox-build, workbox-cli) in modalità "Genera software", questa modifica verrà applicata automaticamente. Tutti questi strumenti produrranno un bundle locale personalizzato del runtime Workbox insieme al codice effettivo necessario per implementare la logica del service worker. In questo scenario, non esiste più alcuna dipendenza su workbox-sw o sulla copia CDN di Workbox. A seconda del valore della configurazione di inlineWorkboxRuntime, il runtime di Workbox verrà suddiviso in un file separato di cui deve essere eseguito il deployment insieme al service worker (se impostato su false, che è l'impostazione predefinita) oppure incluso in linea con la logica del service worker (se impostato su true).

Se utilizzi gli strumenti di creazione in modalità "inject manifest" o se non utilizzi affatto gli strumenti di creazione di Workbox, puoi trovare ulteriori informazioni sulla creazione di un bundle di runtime di Workbox nella guida Utilizzo di bundlers (webpack/aggregazione) con Workbox.

La documentazione e gli esempi per la versione 5 vengono scritti presupponendo che il modulo importi la sintassi, sebbene lo spazio dei nomi workbox.* continuerà a essere supportato in Workbox v5.

Lettura di risposte prememorizzate nella cache

Alcuni sviluppatori devono leggere le risposte pre-memorizzate nella cache direttamente dalla cache, invece di utilizzarle implicitamente tramite il metodo precacheAndRoute(). Un pattern comune nella versione v4 è quello di ottenere prima la chiave cache specifica della versione corrente di una risorsa prememorizzata nella cache, quindi trasmetterla insieme al nome di cache di pre-cache di caches.match() per ottenere Response.

Per semplificare questo processo, workbox-precaching nella v5 supporta un nuovo metodo equivalente, 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`);

Adozione di TypeScript

Nella versione 5, le librerie di runtime di Workbox sono scritte in TypeScript. Anche se continueremo a pubblicare moduli e bundle JavaScript con traslazione per supportare gli sviluppatori che non hanno adottato TypeScript, se utilizzi TypeScript dovresti ricevere informazioni sul tipo accurate e sempre aggiornate direttamente dal progetto Workbox.

Esempio di migrazione

Questo commit illustra una migrazione abbastanza coinvolta, con commenti incorporati. Utilizza l'aggregazione per includere un runtime Workbox personalizzato nel service worker finale invece di caricare il runtime dalla CDN.

Sebbene non contemplino tutte le modifiche che provocano un errore, di seguito sono indicati i prima e il dopo dell'upgrade di un file di service worker dalla v4 alla v5, incluso il passaggio a TypeScript.

Richiedere assistenza

Prevediamo che la maggior parte delle migrazioni sarà semplice. Se riscontri problemi non trattati in questa guida, comunicacelo aprendo un problema su GitHub.