Eseguire la migrazione da Workbox v5 a v6

Questa guida è incentrata sulle modifiche non compatibili introdotte nella versione 6 di Workbox, con esempi delle modifiche da apportare durante l'upgrade dalla versione 5 di Workbox.

Modifiche che provocano un errore

workbox-core

Il metodo skipWaiting() in workbox-core non aggiungerà più un gestore install ed è equivalente alla semplice chiamata di self.skipWaiting().

D'ora in poi, utilizza self.skipWaiting(), poiché skipWaiting() verrà probabilmente rimosso nella versione 7 di Workbox.

workbox-precaching

  • I documenti HTML cross-origin per gli URL corrispondenti a un reindirizzamento HTTP non possono più essere utilizzati per soddisfare una richiesta di navigazione con workbox-precaching. Questo scenario è generalmente insolito.
  • Il parametro di query dell'URL fbclid viene ora ignorato da workbox-precaching quando viene cercata una risposta pre-memorizzata per una determinata richiesta.
  • Il costruttore PrecacheController ora accetta come parametro un oggetto con proprietà specifiche anziché una stringa. Questo oggetto supporta le seguenti proprietà: cacheName (che ha lo stesso scopo della stringa passata al costruttore nella versione 5), plugins (che sostituisce il metodo addPlugins() della versione 5) e fallbackToNetwork (che sostituisce l'opzione simile passata a createHandler() e "createHandlerBoundToURL() nella versione 5).
  • I metodi install() e activate() di PrecacheController ora accettano esattamente un parametro, che deve essere impostato rispettivamente su InstallEvent o ActivateEvent.
  • Il metodo addRoute() è stato rimosso da PrecacheController. Al suo posto, la nuova classe PrecacheRoute può essere utilizzata per creare un percorso che puoi poi registrare.
  • Il metodo precacheAndRoute() è stato rimosso da PrecacheController. Esiste ancora come metodo di assistenza statico esportato dal modulo workbox-precaching. È stato rimosso perché al suo posto è possibile utilizzare PrecacheRoute.
  • Il metodo createMatchCalback() è stato rimosso da PrecacheController. Al suo posto puoi utilizzare il nuovo PrecacheRoute.
  • Il metodo createHandler() è stato rimosso da PrecacheController. Per gestire le richieste, puoi utilizzare la proprietà strategy dell'oggetto PrecacheController.
  • L'esportazione statica di createHandler() è già stata rimossa dal modulo workbox-precaching. Al suo posto, gli sviluppatori devono creare un'istanza PrecacheController e utilizzare la relativa proprietà strategy.
  • Il percorso registrato con precacheAndRoute() ora è un percorso "reale" che utilizza la classe Router di workbox-routing. Ciò può comportare un ordine di valutazione diverso dei percorsi se intersechi le chiamate a registerRoute() e precacheAndRoute().

workbox-routing

Il metodo setDefaultHandler() ora accetta un secondo parametro facoltativo corrispondente al metodo HTTP a cui si applica, con un valore predefinito di 'GET'.

  • Se utilizzi setDefaultHandler() e tutte le tue richieste sono GET, non è necessaria alcuna modifica.
  • Se hai richieste diverse da GET (POST, PUT e così via), setDefaultHandler() non causerà più la corrispondenza di queste richieste.

Configurazione build

L'opzione mode per le modalità getManifest e injectManifest in workbox-build e workbox-cli non era prevista per essere supportata ed è stata rimossa. Questo non si applica a workbox-webpack-plugin, che supporta mode nel plug-in InjectManifest.

Gli strumenti di compilazione richiedono Node.js 10 o versioni successive

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

Nuovi miglioramenti

workbox-strategies

La versione 6 di Workbox introduce un nuovo modo per gli sviluppatori di terze parti di definire le proprie strategie Workbox. In questo modo, gli sviluppatori di terze parti hanno la possibilità di estendere Workbox in modo da soddisfare completamente le loro esigenze.

Nuova classe di base Strategy

Nella versione 6, tutti i classi di strategia Workbox devono estendere la nuova classe di base Strategy. Tutte le strategie predefinite sono state riscritte per supportare questa funzionalità.

La classe di base Strategy è responsabile di due aspetti principali:

  • Richiamo dei callback del ciclo di vita del plug-in comuni a tutti gli handler delle strategie (ad es. quando iniziano, rispondono e terminano).
  • Creazione di un'istanza "handler" che può gestire lo stato di ogni singola richiesta gestita da una strategia.

Nuova classe "handler"

In precedenza avevamo moduli interni chiamati fetchWrapper e cacheWrapper, che (come suggerisce il nome) avvolgono le varie API di recupero e cache con hook nel loro ciclo di vita. Questo è il meccanismo che attualmente consente il funzionamento dei plug-in, ma non è esposto agli sviluppatori.

La nuova classe "handler", StrategyHandler, esporrà questi metodi in modo che le strategie personalizzate possano chiamare fetch() o cacheMatch() e che tutti i plug-in aggiunti all'istanza della strategia vengano invocati automaticamente.

Questo tipo di classe consentirebbe inoltre agli sviluppatori di aggiungere i propri callback personalizzati del ciclo di vita che potrebbero essere specifici per le loro strategie e che "funzionano e basta" con l'interfaccia del plug-in esistente.

Nuovo stato del ciclo di vita del plug-in

In Workbox 5, i plug-in sono stateless. Ciò significa che se una richiesta di /index.html attiva sia i callback requestWillFetch che cachedResponseWillBeUsed, questi due callback non hanno modo di comunicare tra loro o di sapere che sono stati attivati dalla stessa richiesta.

Nella versione 6, a tutti i callback dei plug-in verrà passato anche un nuovo oggetto state. Questo oggetto stato sarà univoco per questo particolare oggetto plug-in e per questa particolare chiamata alla strategia (ovvero la chiamata a handle()). In questo modo, gli sviluppatori possono scrivere plug-in in cui un callback può fare qualcosa in modo condizionale in base a ciò che ha fatto un altro callback nello stesso plug-in (ad es. calcolare il delta di tempo tra l'esecuzione di requestWillFetch e fetchDidSucceed o fetchDidFail).

Nuovi callback del ciclo di vita dei plug-in

Sono stati aggiunti nuovi callback del ciclo di vita dei plug-in per consentire agli sviluppatori di sfruttare appieno lo stato del ciclo di vita dei plug-in:

  • handlerWillStart: viene chiamato prima dell'avvio dell'esecuzione della logica dell'handler. Questo callback può essere utilizzato per impostare lo stato iniziale dell'handler (ad es. registrare l'ora di inizio).
  • handlerWillRespond: viene chiamato prima che il metodo handle() delle strategie restituisca una risposta. Questo callback può essere utilizzato per modificare la risposta prima di restituirla a un gestore di route o ad altra logica personalizzata.
  • handlerDidRespond: viene chiamato dopo che il metodo handle() della strategia restituisce una risposta. Questo callback può essere utilizzato per registrare eventuali dettagli della risposta finale, ad esempio dopo le modifiche apportate da altri plug-in.
  • handlerDidComplete: viene chiamato dopo che tutte le promesse di durata estesa aggiunte all'evento dall'invocazione di questa strategia sono state risolte. Questo callback può essere utilizzato per generare report su tutti i dati che devono attendere il completamento del gestore per essere calcolati (ad es. stato di hit della cache, latenza della cache, latenza della rete).
  • handlerDidError: viene chiamato se l'handler non è stato in grado di fornire una risposta valida da nessuna origine. Questo callback può essere utilizzato per fornire contenuti "di riserva" come alternativa a un errore di rete.

Gli sviluppatori che implementano le proprie strategie personalizzate non devono preoccuparsi di richiamare questi callback autonomamente; tutto viene gestito da una nuova classe di base Strategy.

Tipi TypeScript più precisi per i gestori

Le definizioni di TypeScript per vari metodi di callback sono state normalizzate. Ciò dovrebbe portare a un'esperienza migliore per gli sviluppatori che utilizzano TypeScript e scrivono il proprio codice per implementare o chiamare i gestori.

workbox-window

Nuovo metodo messageSkipWaiting()

Al modulo workbox-window è stato aggiunto un nuovo metodo, messageSkipWaiting(), per semplificare la procedura di attivazione del service worker"in attesa". Ciò offre alcuni miglioramenti:

  • Chiama postMessage() con il corpo del messaggio standard de facto, {type: 'SKIP_WAITING'}, che un worker di servizio generato da Workbox controlla per attivare skipWaiting().
  • Sceglie il service worker "in attesa" corretto a cui pubblicare questo messaggio, anche se non è lo stesso a cui è stato registrato workbox-window.

Rimozione degli eventi "esterni" a favore di una proprietà isExternal

Tutti gli eventi "esterni" in workbox-window sono stati rimossi al posto degli eventi "normali" con una proprietà isExternal impostata su true. In questo modo, gli sviluppatori che si preoccupano della distinzione possono comunque rilevarla, mentre quelli che non ne hanno bisogno possono ignorare la proprietà.

Ricetta più chiara per "Offrire agli utenti la possibilità di ricaricare la pagina"

Grazie a entrambe le modifiche precedenti, la ricetta "Offri un ricaricamento della pagina per gli utenti" può essere semplificata:

// v6:
<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.0.0-alpha.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');

    const showSkipWaitingPrompt = () => {
      // This assumes a hypothetical createUIPrompt() method with
      // onAccept and onReject callbacks:
      const prompt = createUIPrompt({
        onAccept: () => {
          wb.addEventListener('controlling', () => {
            window.location.reload();
          });

          // This will postMessage() to the waiting service worker.
          wb.messageSkipWaiting();
        },

        onReject: () => {
          prompt.dismiss();
        },
      });
    };

    // Listening for externalwaiting is no longer needed.
    wb.addEventListener('waiting', showSkipWaitingPrompt);
    wb.register();
  }
</script>

workbox-routing

Un nuovo parametro booleano, sameOrigin, viene passato alla funzione matchCallback utilizzata in workbox-routing. È impostato su true se la richiesta riguarda un URL con la stessa origine e su false in caso contrario.

In questo modo, vengono semplificate alcune parti comuni:

// In v5:
registerRoute(
  ({url}) =>
    url.origin === self.location.origin && url.pathname.endsWith('.png'),
  new StaleWhileRevalidate({cacheName: 'local-png'})
);

// In v6:
registerRoute(
  ({sameOrigin, url}) => sameOrigin && url.pathname.endsWith('.png'),
  new StaleWhileRevalidate({cacheName: 'local-png'})
);

matchOptions in workbox-expiration

Ora puoi impostare matchOptions in workbox-expiration, che verrà poi trasmesso come CacheQueryOptions alla chiamata cache.delete() sottostante. La maggior parte degli sviluppatori non dovrà farlo.

workbox-precaching

Utilizza workbox-strategies

workbox-precaching è stato riscritto in modo da utilizzare workbox-strategies come base. Ciò non dovrebbe comportare modifiche incompatibili e dovrebbe portare a una maggiore coerenza a lungo termine nel modo in cui i due moduli accedono alla rete e alla cache.

Il pre-caching ora elabora le voci una alla volta, non collettivamente

workbox-precaching è stato aggiornato in modo che venga richiesta e memorizzata nella cache una sola voce del manifest di precache alla volta, anziché tentare di richiederle e memorizzarle tutte contemporaneamente (lasciando al browser il compito di capire come gestire la limitazione).

In questo modo, dovresti ridurre la probabilità di errori net::ERR_INSUFFICIENT_RESOURCES durante la precache e la contesa della larghezza di banda tra la precache e le richieste simultanee effettuate dall'app web.

PrecacheFallbackPlugin consente un fallback offline più semplice

workbox-precaching ora include un PrecacheFallbackPlugin, che implementa il nuovo metodo del ciclo di vita handlerDidError aggiunto nella versione 6.

In questo modo è facile specificare un URL precompilato come "alternativa" per una determinata strategia quando altrimenti non sarebbe disponibile una risposta. Il plug-in si occuperà di creare correttamente la chiave della cache corretta per l'URL precompilato, inclusi eventuali parametri di revisione necessari.

Di seguito è riportato un esempio di utilizzo per rispondere con un /offline.html memorizzato nella cache quando la strategia NetworkOnly non riesce a generare una risposta per una richiesta di navigazione, in altre parole, per visualizzare una pagina HTML offline personalizzata:

import {PrecacheFallbackPlugin, precacheAndRoute} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

// Ensure that /offline.html is part of your precache manifest!
precacheAndRoute(self.__WB_MANIFEST);

registerRoute(
  ({request}) => request.mode === 'navigate',
  new NetworkOnly({
    plugins: [
      new PrecacheFallbackPlugin({
        fallbackURL: '/offline.html',
      }),
    ],
  })
);

precacheFallback nella memorizzazione nella cache in fase di runtime

Se utilizzi generateSW per creare un servizio worker per te anziché scriverlo manualmente, puoi utilizzare la nuova opzione di configurazione precacheFallback in runtimeCaching per ottenere lo stesso risultato:

{
  // ... other generateSW config options...
  runtimeCaching: [{
    urlPattern: ({request}) => request.mode === 'navigate',
    handler: 'NetworkOnly',
    options: {
      precacheFallback: {
        // This URL needs to be included in your precache manifest.
        fallbackURL: '/offline.html',
      },
    },
  }],
}

Risorse di assistenza

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