Questo codelab fa parte del corso di formazione Developing Progressive Web Apps, sviluppato dal team Google Training Training. Otterrai il massimo valore da questo corso se lavori in sequenza nei codelab.
Per i dettagli completi sul corso, consulta la panoramica sullo sviluppo di app web progressive.
Introduzione
Questo lab illustra come creare un service worker semplice e spiega il ciclo di vita del service worker.
Obiettivi didattici
- Crea uno script service worker di base, installalo ed esegui il debug semplice
Che cosa devi sapere
- JavaScript e HTML di base
- Concetti e sintassi di base di ES2015 Promi
- Come attivare la Console per gli sviluppatori
Cosa ti serve prima di iniziare
- Computer con accesso terminali/shell
- Connessione a Internet
- Un browser che supporta i service worker.
- Un editor di testo
Scarica o clona il repository pwa-training-labs da github e installa la versione LTS di Node.js, se necessario.
Accedi alla directory service-worker-lab/app/
e avvia un server di sviluppo locale:
cd service-worker-lab/app npm install node server.js
Puoi arrestare il server in qualsiasi momento con Ctrl-c
.
Apri il browser e vai alla pagina localhost:8081/
.
Nota: annulla la registrazione di tutti i service worker e cancella tutte le cache di service worker per localhost, in modo da non interferire con il lab. In Chrome DevTools, puoi accedere a Cancella dati sito dalla sezione Cancella spazio di archiviazione della scheda Applicazione.
Apri la cartella service-worker-lab/app/
nell'editor di testo che preferisci. La cartella app/
è il luogo in cui creerai il lab.
Questa cartella contiene:
below/another.html
,js/another.js
,js/other.js
eother.html
sono risorse di esempio che utilizziamo per sperimentare l'ambito del service worker- La cartella
styles/
contiene i fogli di stile a cascata per questo lab - La cartella
test/
contiene file che consentono di verificare l'avanzamento index.html
è la pagina HTML principale del nostro sito/applicazione di esempioservice-worker.js
è il file JavaScript utilizzato per creare il nostro service workerpackage.json
epackage-lock.json
monitorano i pacchetti di nodi utilizzati in questo progettoserver.js
è un semplice server espresso che utilizziamo per ospitare la nostra app
Apri service-worker.js
nell'editor di testo. Tieni presente che il file è vuoto. Non abbiamo ancora aggiunto alcun codice da eseguire all'interno del service worker.
Apri index.html
nell'editor di testo.
All'interno dei tag <script>
, aggiungi il codice seguente per registrare il service worker:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('service-worker.js')
.then(registration => {
console.log('Service Worker is registered', registration);
})
.catch(err => {
console.error('Registration failed:', err);
});
});
}
Salva lo script e aggiorna la pagina. La console dovrebbe restituire un messaggio che indica che il service worker è stato registrato. In Chrome, puoi verificare che un service worker sia registrato aprendo DevTools (Ctrl + Maiusc + I su Windows e Linux o ⌘ + Alt + I su Mac), facendo clic sulla scheda Applicazione e quindi sull'opzione Service worker. Il risultato dovrebbe essere simile al seguente:
(Facoltativo) Apri il sito su un browser non supportato e verifica che il controllo di supporto condizionale.
Spiegazione
Il codice riportato sopra registra il file service-worker.js
come service worker. Verifica innanzitutto se il browser supporta i service worker. Questa operazione deve essere eseguita ogni volta che registri un service worker perché alcuni browser potrebbero non supportare i service worker. Il codice registra quindi il service worker utilizzando il metodo register
dell'API ServiceWorkerContainer
, presente nell'interfaccia di Navigator
di Windows.
navigator.serviceWorker.register(...)
restituisce una promessa che si risolve con un oggetto registration
una volta registrato il service worker. In caso contrario, la promessa verrà rifiutata.
Le modifiche allo stato del service worker attivano gli eventi nel service worker.
Aggiungi listener di eventi
Apri service-worker.js
nell'editor di testo.
Aggiungi i seguenti listener di eventi per il service worker:
self.addEventListener('install', event => {
console.log('Service worker installing...');
// Add a call to skipWaiting here
});
self.addEventListener('activate', event => {
console.log('Service worker activating...');
});
Salva il file.
Annulla manualmente la registrazione del service worker e aggiorna la pagina per installare e attivare il service worker aggiornato. Il log della console dovrebbe indicare che il nuovo service worker è stato registrato, installato e attivato.
Nota: il log di registrazione potrebbe risultare non conforme agli altri log (installazione e attivazione). Il service worker viene eseguito contemporaneamente alla pagina, quindi non possiamo garantire l'ordine dei log (il log di registrazione proviene dalla pagina, mentre i log di installazione e attivazione provengono dal service worker). Tuttavia, l'installazione, l'attivazione e altri eventi del service worker avvengono in un ordine definito all'interno del service worker, che dovrebbe sempre comparire nell'ordine previsto.
Spiegazione
Il service worker emette un evento install
al termine della registrazione. Nel codice riportato sopra, viene registrato un messaggio all'interno del listener di eventi install
, ma in un'app reale è l'ideale per memorizzare nella cache gli asset statici.
Quando viene registrato un service worker, il browser rileva se è un nuovo service worker (perché è diverso da quello installato in precedenza o perché non è presente alcun service worker registrato per questo sito). Se il service worker è nuovo (come in questo caso), allora il browser lo installa.
Quando prende il controllo della pagina, il service worker emette un evento activate
. Il codice riportato sopra registra un messaggio qui, ma questo evento viene spesso utilizzato per aggiornare le cache.
È possibile attivare un solo service worker alla volta per un determinato ambito (vedi Esplorazione del service worker). Di conseguenza, un service worker appena installato non viene attivato finché il service worker esistente non è più in uso. Questo è il motivo per cui tutte le pagine controllate da un service worker devono essere chiuse prima che un nuovo service worker possa prendere il controllo. Poiché abbiamo annullato la registrazione del service worker esistente, questo è stato attivato immediatamente.
Nota: l'aggiornamento della pagina non è sufficiente per trasferire il controllo a un nuovo service worker, perché la nuova pagina verrà richiesta prima dell'unload della pagina corrente e non ci sarà un momento in cui il vecchio service worker non sarà in uso.
Nota:puoi anche attivare manualmente un nuovo service worker utilizzando alcuni browser e strumenti per sviluppatori e in modo programmatico con skipWaiting()
, illustrato nella sezione 3.4.
Aggiorna il service worker
Aggiungi il seguente commento in service-worker.js
:
// I'm a new service worker
Salva il file e aggiorna la pagina. Esamina i log nella console. Tieni presente che il nuovo service worker viene installato ma non attivato. In Chrome, puoi visualizzare il service worker in attesa nella scheda Application di DevTools.
Chiudi tutte le pagine associate al service worker. Dopodiché, riapri il localhost:8081/
. Il log della console dovrebbe indicare che il nuovo service worker è stato attivato.
Nota: se ricevi risultati imprevisti, assicurati che la cache HTTP sia disattivata negli strumenti per sviluppatori.
Spiegazione
Il browser rileva una differenza di byte tra il file del nuovo service worker e quello esistente (a causa del commento aggiunto), quindi è installato il nuovo service worker. Poiché può essere attivo un solo service worker alla volta (per un determinato ambito), anche se il nuovo service worker è installato, non può essere attivato finché il service worker esistente non è più in uso. Chiudendo tutte le pagine sotto il controllo del vecchio service worker, possiamo attivare il nuovo service worker.
Ignorare la fase di attesa
È possibile che un nuovo service worker venga attivato immediatamente, anche se è presente un service worker esistente, saltando la fase di attesa.
In service-worker.js
, aggiungi una chiamata a skipWaiting
nel listener di eventi install
:
self.skipWaiting();
Salva il file e aggiorna la pagina. Nota che il nuovo service worker viene installato e attivato immediatamente, anche se era sotto il controllo di un precedente service worker.
Spiegazione
Il metodo skipWaiting()
consente a un service worker di attivarsi non appena termina l'installazione. Il listener di eventi di installazione è un punto comune per chiamare skipWaiting()
, ma può essere chiamato ovunque durante o prima della fase di attesa. Consulta questa documentazione per ulteriori informazioni su quando e come utilizzare skipWaiting()
. Per il resto del lab, possiamo testare il nuovo codice del service worker senza annullare manualmente la registrazione del service worker.
Per avere ulteriori informazioni
I service worker possono fungere da proxy tra l'app web e la rete.
Aggiungi un listener di recupero per intercettare le richieste del nostro dominio.
Aggiungi il seguente codice a service-worker.js
:
self.addEventListener('fetch', event => {
console.log('Fetching:', event.request.url);
});
Salva lo script e aggiorna la pagina per installare e attivare il service worker aggiornato.
Controlla la console e osserva che non sono stati registrati eventi di recupero. Aggiorna la pagina e controlla nuovamente la console. Questa volta dovresti visualizzare gli eventi di recupero della pagina e dei relativi asset (ad esempio il codice CSS).
Fai clic sui link Altre pagine, Altra pagina e Indietro.
Nella console, vedrai gli eventi di recupero per ciascuna delle pagine e le relative risorse. Tutti i log hanno senso?
Nota: se visiti una pagina e non hai disattivato la cache HTTP, gli asset CSS e JavaScript potrebbero essere memorizzati nella cache locale. In questo caso, non vedrai gli eventi di recupero per queste risorse.
Spiegazione
Il service worker riceve un evento fetch per ogni richiesta HTTP effettuata dal browser nell'ambito. L'oggetto evento di recupero contiene la richiesta. L'ascolto degli eventi di recupero nel service worker è simile all'ascolto degli eventi di clic nel DOM. Nel nostro codice, quando si verifica un evento di recupero, registriamo l'URL richiesto alla console (in pratica possiamo anche creare e restituire la nostra risposta personalizzata con risorse arbitrarie).
Perché gli eventi di recupero non vengono registrati al primo aggiornamento? Per impostazione predefinita, il recupero degli eventi da una pagina non viene eseguito da un service worker se non riceve la richiesta stessa. Ciò garantisce coerenza nel sito; se una pagina viene caricata senza il service worker, lo fa anche le relative risorse secondarie.
Per avere ulteriori informazioni
- Evento di recupero - MDN
- Utilizzo del metodo di recupero - MDN
- Introduzione a Fetch - Google Developers
Codice soluzione
Per recuperare una copia del codice funzionante, vai alla cartella 04-intercepting-network-requests/
.
I service worker hanno l'ambito. L'ambito del service worker determina da quali percorsi intercetta le richieste.
Trova l'ambito
Aggiorna il codice di registrazione in index.html
con:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('service-worker.js')
.then(registration => {
console.log('SW registered with scope:', registration.scope);
})
.catch(err => {
console.error('Registration failed:', err);
});
});
}
Aggiorna il browser. Tieni presente che la console mostra l'ambito del service worker (in questo caso http://localhost:8081/
).
Spiegazione
La promessa restituita da register()
si risolve nell'oggetto di registrazione, che contiene l'ambito del service worker.
L'ambito predefinito è il percorso del file del service worker e si estende a tutte le directory inferiori. Di conseguenza, un service worker nella directory principale di un'app controlla le richieste di tutti i file al suo interno.
Spostamento del service worker
Sposta service-worker.js
nella directory below/
e aggiorna l'URL del service worker nel codice di registrazione in index.html
.
Annulla la registrazione dell'attuale service worker nel browser e aggiorna la pagina.
La console mostra che l'ambito del service worker è ora http://localhost:8081/below/
. In Chrome, puoi anche visualizzare l'ambito del service worker nella scheda Application di DevTools:
Torna alla pagina principale e fai clic su Altra pagina, Altra pagina e Indietro. Quali richieste di recupero vengono registrate? Quali non sono?
Spiegazione
L'ambito predefinito del service worker è il percorso del file del service worker. Poiché il file del service worker ora si trova in below/
, questo è il suo ambito. Ora la console registra solo gli eventi di recupero per another.html
, another.css
e another.js
, perché queste sono le uniche risorse presenti nell'ambito del service worker.
Imposta un ambito arbitrario
Sposta di nuovo il service worker nella directory radice del progetto (app/
) e aggiorna l'URL del service worker nel codice di registrazione in index.html
.
Utilizza il riferimento su MDN per impostare l'ambito del service worker alla directory below/
utilizzando il parametro facoltativo in register()
.
Annulla la registrazione del service worker e aggiorna la pagina. Fai clic su Altra pagina, Un'altra pagina e Indietro.
Ancora una volta la console mostra che l'ambito del service worker è ora http://localhost:8081/below/
e i log recuperano solo gli eventi per another.html
, another.css
e another.js
.
Spiegazione
È possibile impostare un ambito arbitrario passando a un parametro aggiuntivo durante la registrazione, ad esempio:
navigator.serviceWorker.register('/service-worker.js', {
scope: '/kitten/'
});
Nell'esempio precedente, l'ambito del service worker è impostato su /kitten/
. Il service worker intercetta le richieste dalle pagine di /kitten/
e /kitten/lower/
, ma non quelle di pagine come /kitten
o /
.
Nota: non puoi impostare un ambito arbitrario sopra la posizione effettiva del service worker. Tuttavia, se il server worker è attivo su un client utilizzato con l'intestazione Service-Worker-Allowed
, puoi specificare un ambito massimo per il service worker sopra la località del service worker.
Per avere ulteriori informazioni
Codice soluzione
Per recuperare una copia del codice funzionante, vai alla cartella solution/
.
Ora un service worker semplice è in funzione e comprende il ciclo di vita del service worker.
Per avere ulteriori informazioni
Per visualizzare tutti i codelab nel corso di formazione per PWA, vedi il codelab di benvenuto per il corso/