Il pacchetto workbox-window
è un insieme di moduli che devono essere eseguiti
window
contesto, che
è dire all'interno delle tue pagine web. Si integrano con gli altri strumenti
e pacchetti eseguiti nel service worker.
Le funzionalità e gli obiettivi principali di workbox-window
sono:
- Per semplificare il processo di registrazione e aggiornamento dei service worker aiutando gli sviluppatori identificano i momenti più critici del ciclo di vita dei service worker e semplificano per rispondere a questi momenti.
- Per evitare che gli sviluppatori commettano gli errori più comuni.
- Per favorire una comunicazione più semplice tra il codice in esecuzione nel service worker e il codice in esecuzione nella finestra.
Importazione e utilizzo della finestra di lavoro
Il punto di accesso principale per il pacchetto workbox-window
è la classe Workbox
e
puoi importarlo nel tuo codice dalla nostra rete CDN o utilizzando uno dei
di raggruppamento di JavaScript.
Utilizzo della nostra rete CDN
Il modo più semplice per importare la classe Workbox
sul tuo sito è dalla nostra CDN:
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
Tieni presente che questo esempio utilizza <script type="module">
e l'istruzione import
per
carica il corso Workbox
. Anche se si può pensare di dover affrontare questo
per farlo funzionare nei browser meno recenti, in realtà non è necessario.
Tutti i principali browser che supportano il service worker supportano anch'essi moduli JavaScript nativi, quindi sono perfette la pubblicazione di questo codice su tutti i browser (i browser meno recenti lo ignorano).
Caricamento di Workbox con i bundler JavaScript
Sebbene non siano assolutamente necessari strumenti per utilizzare workbox-window
, se
la tua infrastruttura di sviluppo include già
un bundler come
webpack o Rollup che funzioni
con dipendenze npm, è possibile utilizzarle
carica workbox-window
.
Il primo passaggio consiste nel
installa
workbox-window
come dipendenza della tua applicazione:
npm install workbox-window
Poi, in uno dei file JavaScript della tua applicazione, import
casella di lavoro per
riferimento al nome del pacchetto workbox-window
:
import {Workbox} from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
Se il bundler supporta la suddivisione del codice tramite istruzioni di importazione dinamica,
puoi anche caricare workbox-window
in modo condizionale, il che dovrebbe aiutare a ridurre
dimensioni del bundle principale della pagina.
Anche se workbox-window
è abbastanza piccolo, non c'è motivo
deve essere caricato con la logica principale dell'applicazione del sito, come service worker,
per loro stessa natura, sono un miglioramento progressivo.
if ('serviceWorker' in navigator) {
const {Workbox} = await import('workbox-window');
const wb = new Workbox('/sw.js');
wb.register();
}
Concetti avanzati sul raggruppamento
A differenza dei pacchetti Workbox eseguiti nel service worker, i file di build
a cui fa riferimentoworkbox-window
main
e
module
in
package.json
vengono trasferiti a ES5. Questo le rende compatibili con le
di sviluppo software, alcuni dei quali non consentono agli sviluppatori di
le rispettive dipendenze node_module
.
Se il sistema di build ti consente di eseguire il transpile delle dipendenze (o non devi eseguire il transpile del codice), è preferibile importare una data non del pacchetto stesso.
Di seguito sono riportati i vari modi per importare Workbox
, oltre a una spiegazione delle
che cosa restituirà:
// Imports a UMD version with ES5 syntax
// (pkg.main: "build/workbox-window.prod.umd.js")
const {Workbox} = require('workbox-window');
// Imports the module version with ES5 syntax
// (pkg.module: "build/workbox-window.prod.es5.mjs")
import {Workbox} from 'workbox-window';
// Imports the module source file with ES2015+ syntax
import {Workbox} from 'workbox-window/Workbox.mjs';
Esempi
Dopo aver importato il corso Workbox
, puoi utilizzarlo per registrarti e
interagire con il tuo service worker. Ecco alcuni esempi di possibili utilizzi
Workbox
nella tua applicazione:
Registra un service worker e invia una notifica all'utente la prima volta che il service worker è attivo
Molte applicazioni web utilizzano il service worker per prememorizzare nella cache gli asset in modo che l'app funzioni offline nei caricamenti pagina successivi. In alcuni casi potrebbe essere opportuno informare all'utente che l'app è ora disponibile offline.
const wb = new Workbox('/sw.js');
wb.addEventListener('activated', event => {
// `event.isUpdate` will be true if another version of the service
// worker was controlling the page when this version was registered.
if (!event.isUpdate) {
console.log('Service worker activated for the first time!');
// If your service worker is configured to precache assets, those
// assets should all be available now.
}
});
// Register the service worker after event listeners have been added.
wb.register();
Invia una notifica all'utente se un service worker è stato installato ma è bloccato in attesa di attivazione
Quando una pagina controllata da un service worker esistente registra un nuovo servizio worker, per impostazione predefinita il service worker non si attiverà fino a quando tutti i client controllati dal service worker iniziale hanno eseguito l'unload.
Si tratta di una fonte di confusione comune per gli sviluppatori, soprattutto nei casi in cui il ricaricamento della pagina corrente non comporta l'attivazione del nuovo service worker.
Per ridurre al minimo la confusione e chiarire quando si verifica questa situazione,
il corso Workbox
fornisce un evento waiting
che puoi ascoltare:
const wb = new Workbox('/sw.js');
wb.addEventListener('waiting', event => {
console.log(
`A new service worker has installed, but it can't activate` +
`until all tabs running the current version have fully unloaded.`
);
});
// Register the service worker after event listeners have been added.
wb.register();
Invia una notifica all'utente riguardo agli aggiornamenti della cache inviati dal pacchetto workbox-broadcast-update
Il pacchetto workbox-broadcast-update
è un ottimo modo per pubblicare contenuti dalla cache (per una distribuzione rapida), ma anche
la possibilità di informare l'utente degli aggiornamenti apportati a tali contenuti (utilizzando
strategia inattiva-durante-riconvalida).
Per ricevere questi aggiornamenti dalla finestra, puoi ascoltare message
eventi di
tipo CACHE_UPDATED
:
const wb = new Workbox('/sw.js');
wb.addEventListener('message', event => {
if (event.data.type === 'CACHE_UPDATED') {
const {updatedURL} = event.data.payload;
console.log(`A newer version of ${updatedURL} is available!`);
}
});
// Register the service worker after event listeners have been added.
wb.register();
Invia al service worker un elenco di URL da memorizzare nella cache
Per alcune applicazioni è possibile conoscere tutti gli asset che devono essere vengono prememorizzati nella cache in fase di creazione, ma alcune applicazioni offrono pagine completamente diverse in base al primo URL al quale viene indirizzato l'utente.
Per le app di quest'ultima categoria, potrebbe avere senso memorizzare nella cache solo gli asset
necessario all'utente per la pagina specifica che ha visitato. Quando utilizzi il
workbox-routing
, puoi
invia al router un elenco di URL da memorizzare nella cache, che verranno memorizzati nella cache in base
alle regole definite sul router stesso.
Questo esempio invia al router un elenco di URL caricati dalla pagina ogni volta che viene è attivato un nuovo service worker. Tieni presente che puoi inviare tutti gli URL perché solo gli URL che corrispondono a una route definita nel service worker verranno memorizzati nella cache:
const wb = new Workbox('/sw.js');
wb.addEventListener('activated', event => {
// Get the current page URL + all resources the page loaded.
const urlsToCache = [
location.href,
...performance.getEntriesByType('resource').map(r => r.name),
];
// Send that list of URLs to your router in the service worker.
wb.messageSW({
type: 'CACHE_URLS',
payload: {urlsToCache},
});
});
// Register the service worker after event listeners have been added.
wb.register();
Momenti importanti del ciclo di vita dei service worker
Il ciclo di vita del Service worker è complessa e può essere difficile da capire a fondo. In parte così complessa da dover gestire tutti i casi limite per tutti i possibili usi service worker (ad es. registrare più di un service worker, registrare in frame diversi, registrando i Service worker con nomi diversi e così via).
Tuttavia, la maggior parte degli sviluppatori che implementano i service worker non dovrebbe preoccuparsi a tutti questi casi limite perché il loro utilizzo è piuttosto semplice. La maggior parte degli sviluppatori registrano un solo service worker per caricamento pagina e non modificano il nome del service worker il file distribuito sul server.
La classe Workbox
adotta questa vista più semplice del ciclo di vita del service worker
suddividendo tutte le registrazioni dei service worker in due categorie:
un service worker registrato e un service worker esterno:
- Service worker registrato: un service worker che ha avviato l'installazione come
risultato dell'istanza
Workbox
che chiamaregister()
o dell'istanza già attiva il service worker se la chiamata aregister()
non ha attivato un eventoupdatefound
nella registrazione. - Service worker esterno:un service worker che ha avviato l'installazione
indipendentemente dall'istanza
Workbox
che chiamaregister()
. Questo di solito Si verifica quando una nuova versione del tuo sito è aperta in un'altra scheda di un utente. Quando ha origine da un service worker esterno, il valoreisExternal
verrà impostata sutrue
.
Tenendo a mente questi due tipi di service worker, ecco un'analisi dettagliata momenti del ciclo di vita dei service worker, insieme ai suggerimenti per gli sviluppatori su come gestirle:
Alla prima installazione di un service worker
Probabilmente vorrai trattare la primissima installazione di un service worker in modo diverso rispetto a come trattate tutti gli aggiornamenti futuri.
In workbox-window
, puoi prima distinguere tra le versioni
installazione e aggiornamenti futuri controllando la proprietà isUpdate
su uno dei
i seguenti eventi. Per la primissima installazione, isUpdate
false
.
const wb = new Workbox('/sw.js');
wb.addEventListener('installed', event => {
if (!event.isUpdate) {
// First-installed code goes here...
}
});
wb.register();
Quando viene trovata una versione aggiornata del service worker
Quando inizia l'installazione di un nuovo service worker, ma al momento è presente una versione esistente
il controllo della pagina, la proprietà isUpdate
di tutti i seguenti eventi
true
.
Il modo in cui reagisci in questa situazione è in genere diverso dalla prima perché devi stabilire quando e come l'utente riceve l'aggiornamento.
Quando viene trovata una versione imprevista del service worker
A volte gli utenti mantengono il tuo sito aperto in una scheda in background per molto tempo nel tempo. Potrebbero persino aprire una nuova scheda e visitare il tuo sito senza rendersi conto hanno già il tuo sito aperto in una scheda in secondo piano. In questi casi è possibile eseguire contemporaneamente due versioni del sito, possono presentare alcuni problemi interessanti per lo sviluppatore.
Considera uno scenario in cui la scheda A è in esecuzione nella versione 1 del sito e nella scheda B con la versione v2. Quando viene caricata la scheda B, viene controllata dalla versione del servizio worker fornito con la versione v1, ma la pagina restituita dal server (se viene utilizzato un strategia di memorizzazione nella cache incentrata sulla rete per le richieste di navigazione) conterrà tutti gli asset v2.
Questo di solito non è un problema per la scheda B, dato che quando hai scritto la versione 2 di Google, conoscevi il funzionamento del codice v1. Tuttavia, potrebbe essere necessario problema per la scheda A, poiché il codice v1 non poteva prevedere cosa che potrebbero essere introdotte dal codice v2.
Per gestire queste situazioni, workbox-window
invia anche il ciclo di vita
eventi quando rileva un aggiornamento da un "esterno" il service worker, dove
"link" indica semplicemente una versione diversa da quella Workbox
corrente.
Istanza registrata.
A partire da Workbox v6, questi eventi sono equivalenti agli eventi documentati
sopra, con l'aggiunta di una proprietà isExternal: true
impostata per ogni evento
. Se la tua applicazione web deve implementare una logica specifica per gestire una
"esterni" service worker, puoi controllare quella proprietà nei tuoi gestori di eventi.
Evitare errori comuni
Una delle funzionalità più utili offerte da Workbox è il logging degli sviluppatori. e
questo è particolarmente vero per workbox-window
.
Sappiamo che lo sviluppo con il service worker può spesso essere fonte di confusione e avvengono in contrasto con ciò che ti aspetti, può essere difficile capire il motivo.
Ad esempio, quando apporti una modifica al service worker e ricarichi la pagina, potresti non vedere questa modifica nel browser. Il motivo più probabile è che che il tuo service worker è ancora in attesa di essere attivato.
Ma quando registri un service worker per la classe Workbox
, devi
essere informato di tutte le modifiche allo stato del ciclo di vita nella console per gli sviluppatori,
è utile per eseguire il debug delle cose non come ci si aspetterebbe.
Inoltre, un errore comune che gli sviluppatori commettono al primo utilizzo del service worker è per registrare un service worker nel ambito errato.
Per evitare che ciò accada, il corso Workbox
ti avviserà se:
che registra il service worker non rientra nell'ambito di quel service worker. Verrà
ti avvisa anche nei casi in cui il service worker è attivo, ma non ancora
il controllo della pagina:
Finestra di comunicazione con il service worker
L'utilizzo più avanzato dei service worker comporta una grande quantità di messaggi tra
il service worker e la finestra. Il corso Workbox
è utile anche in questo
fornendo un metodo messageSW()
, che postMessage()
l'istanza
service worker registrato e attendere una risposta.
Sebbene sia possibile inviare dati al service worker in qualsiasi formato, il formato da tutti i pacchetti Workbox è un oggetto con tre proprietà (le ultime due sono facoltativo):
I messaggi inviati con il metodo messageSW()
utilizzano MessageChannel
in modo che il destinatario
possono rispondere. Per rispondere a un messaggio puoi chiamare
event.ports[0].postMessage(response)
nel listener di eventi di messaggi. La
Il metodo messageSW()
restituisce una promessa che si risolverà in qualsiasi response
con cui rispondi.
Di seguito è riportato un esempio di invio di messaggi dalla finestra al service worker
ricevere una risposta. Il primo blocco di codice è il listener dei messaggi nella
service worker e il secondo blocco utilizza la classe Workbox
per inviare
messaggio e attendi la risposta:
Codice in sw.js:
const SW_VERSION = '1.0.0';
addEventListener('message', event => {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
});
Codice in main.js (in esecuzione nella finestra):
const wb = new Workbox('/sw.js');
wb.register();
const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);
Gestione delle incompatibilità delle versioni
L'esempio precedente mostra come implementare il controllo del service worker personalizzata dalla finestra. Questo esempio viene utilizzato perché quando invii i messaggi tra la finestra e il service worker, è fondamentale tieni presente che il tuo service worker potrebbe non eseguire la stessa versione sul sito che il codice della pagina è in esecuzione e la soluzione per problema è diverso a seconda che le pagine vengano pubblicate o meno in base alla rete o cache-first.
Prima rete
Quando vengono pubblicate per prime le pagine sulla rete, gli utenti ricevono sempre l'ultima versione del codice HTML dal tuo server. Tuttavia, la prima volta che un utente visita di nuovo il sito (dopo avere implementato un aggiornamento), il codice HTML che riceveranno sarà per l'ultima versione, ma il service worker in esecuzione nel browser una versione installata in precedenza (forse molte versioni precedenti).
È importante comprendere questa possibilità perché se il codice JavaScript viene caricato dalla versione corrente della pagina invia un messaggio a una versione precedente del un service worker, quella versione potrebbe non sapere come rispondere (o potrebbe rispondere in un formato non compatibile).
Di conseguenza, è opportuno eseguire sempre la versione del service worker e controllare per le versioni compatibili prima di eseguire operazioni critiche.
Ad esempio, nel codice precedente, se la versione del service worker restituita da quel
La chiamata messageSW()
è precedente alla versione prevista, sarebbe opportuno attendere
finché non viene trovato un aggiornamento (dovrebbe verificarsi quando chiami il numero register()
). Alle ore
A quel punto puoi inviare una notifica all'utente o
un aggiornamento, oppure puoi
salta la fase di attesa
per attivare subito il nuovo service worker.
Prima cache
A differenza di quando pubblichi le pagine principalmente sulla rete, quando le pubblichi
vengono memorizzate nella cache.
sappi che la versione della tua pagina sarà inizialmente sempre
il tuo service worker (perché è quello che lo ha fornito). Di conseguenza, è sicuro
per utilizzare subito messageSW()
.
Tuttavia, se viene trovata una versione aggiornata del Service worker che attiva
quando la tua pagina chiama register()
(ossia salti intenzionalmente la fase di attesa),
potrebbe non essere più sicuro inviargli messaggi.
Una strategia per gestire questa possibilità è utilizzare uno schema di controllo delle versioni che consente di distinguere tra aggiornamenti non permanenti e aggiornamenti permanenti, e, nel caso di un aggiornamento che provoca un errore, non è sicuro inviare un messaggio con il Service worker. È meglio invece avvisare l'utente che sta eseguendo una versione della pagina e suggerisci di ricaricare per ricevere l'aggiornamento.
Salta l'assistente in attesa
Una convenzione di utilizzo comune per la messaggistica window to service worker è l'invio di un
{type: 'SKIP_WAITING'}
messaggio per indicare a un service worker installato di
salta la fase di attesa
e attiva.
A partire da Workbox v6, il metodo messageSkipWaiting()
può essere utilizzato per inviare un
Messaggio {type: 'SKIP_WAITING'}
al service worker in attesa associato al
registrazione attuale del Service worker. In silenzio, non fa nulla se non è presente
in attesa del service worker.
Tipi
Workbox
Una classe che aiuta a gestire la registrazione, gli aggiornamenti e gli aggiornamenti dei service worker reagire agli eventi del ciclo di vita dei service worker.
Proprietà
-
costruttore
null
Crea una nuova istanza di Workbox con un URL dello script e un service worker le opzioni di CPU e memoria disponibili. L'URL e le opzioni dello script sono gli stessi utilizzati quando chiamata a navigator.serviceWorker.register(scriptURL, options).
La funzione
constructor
ha questo aspetto:(scriptURL: string | TrustedScriptURL, registerOptions?: object) => {...}
-
scriptURL
string | TrustedScriptURL
Script del service worker associati a questa istanza. L'utilizzo di un L'app
TrustedScriptURL
è supportata. -
registerOptions
oggetto facoltativo
-
returns
-
-
attivo
Promise<ServiceWorker>
-
controllo
Promise<ServiceWorker>
-
getSW
null
Restituisce un riferimento a un service worker che corrisponde all'URL dello script di questa istanza, non appena è disponibile.
Se al momento della registrazione è già presente un servizio attivo o in attesa worker con un URL dello script corrispondente, verrà utilizzato (con il service worker ha la precedenza sul service worker attivo se entrambi poiché il service worker in attesa sarebbe stato registrato più di recente). Se non esiste un service worker attivo o in attesa corrispondente al momento della registrazione nel tempo, la promessa non si risolve finché non viene trovato un aggiornamento e non inizia in fase di installazione. A quel punto viene utilizzato il service worker per l'installazione.
La funzione
getSW
ha questo aspetto:() => {...}
-
returns
Promise<ServiceWorker>
-
-
messageSW
null
Invia l'oggetto dati passato al service worker registrato da questo dell'istanza (tramite
workbox-window.Workbox#getSW
) e risolve con una risposta (se presente).Una risposta può essere impostata in un gestore di messaggi nel service worker chiamando
event.ports[0].postMessage(...)
, il che risolverà la promessa restituito damessageSW()
. Se non viene impostata alcuna risposta, la promessa non risolvere il problema.La funzione
messageSW
ha questo aspetto:(data: object) => {...}
-
dati
oggetto
Un oggetto da inviare al service worker
-
returns
Promesso<qualsiasi>
-
-
messageSkipWaiting
null
Invia un messaggio
{type: 'SKIP_WAITING'}
al service worker attualmente nello statowaiting
associato alla registrazione attuale.Se non è attualmente presente una registrazione o se il service worker è
waiting
, la chiamata non avrà alcun effetto.La funzione
messageSkipWaiting
ha questo aspetto:() => {...}
-
register
null
Registra un service worker per l'URL e il servizio dello script di questa istanza delle risorse dei worker. Per impostazione predefinita, questo metodo ritarda la registrazione fino al giorno la finestra è stata caricata.
La funzione
register
ha questo aspetto:(options?: object) => {...}
-
opzioni
oggetto facoltativo
-
nelle immediate vicinanze
booleano facoltativo
-
-
returns
Promise<ServiceWorkerRegistration>
-
-
update
null
Verifica la presenza di aggiornamenti del service worker registrato.
La funzione
update
ha questo aspetto:() => {...}
-
returns
Promesso<void>
-
WorkboxEventMap
Proprietà
-
attivato
-
attivazione in corso...
-
controllo
-
installata
-
installazione in corso...
-
messaggio
-
ridondante
-
in attesa
WorkboxLifecycleEvent
Proprietà
-
isExternal
booleano facoltativo
-
isUpdate
booleano facoltativo
-
originalEvent
Evento facoltativo
-
sw
ServiceWorker facoltativo
-
target
WorkboxEventTarget facoltativo
-
tipo
typeOperator
WorkboxLifecycleEventMap
Proprietà
-
attivato
-
attivazione in corso...
-
controllo
-
installata
-
installazione in corso...
-
ridondante
-
in attesa
WorkboxLifecycleWaitingEvent
Proprietà
-
isExternal
booleano facoltativo
-
isUpdate
booleano facoltativo
-
originalEvent
Evento facoltativo
-
sw
ServiceWorker facoltativo
-
target
WorkboxEventTarget facoltativo
-
tipo
typeOperator
-
wasWaitingBeforeRegister
booleano facoltativo
WorkboxMessageEvent
Proprietà
-
dati
qualsiasi
-
isExternal
booleano facoltativo
-
originalEvent
Evento
-
ports
typeOperator
-
sw
ServiceWorker facoltativo
-
target
WorkboxEventTarget facoltativo
-
tipo
"messaggio"
Metodi
messageSW()
workbox-window.messageSW(
sw: ServiceWorker,
data: object,
)
Invia un oggetto dati a un service worker tramite postMessage
e si risolve con
una risposta (se presente).
Una risposta può essere impostata in un gestore di messaggi nel service worker
chiamando event.ports[0].postMessage(...)
, il che risolverà la promessa
restituito da messageSW()
. Se non viene impostata alcuna risposta, la promessa non
risolvere il problema.
Parametri
-
sw
ServiceWorker
Il service worker a cui inviare il messaggio.
-
dati
oggetto
Un oggetto da inviare al service worker.
Resi
-
Promesso<qualsiasi>