Questo codelab fa parte del corso di formazione Sviluppare app web progressive, sviluppato dal team di formazione di Google Developers. Per ottenere il massimo valore da questo corso, ti consigliamo di seguire le codelab in sequenza.
Per i dettagli completi sul corso, consulta la panoramica sullo sviluppo di app web progressive.
Introduzione
Questo lab ti guida nella creazione di 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 delle promesse ES2015
- Come attivare la console per gli sviluppatori
Cosa ti serve prima di iniziare
- Computer con accesso al terminale/alla 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.
Vai alla directory service-worker-lab/app/ e avvia un server di sviluppo locale:
cd service-worker-lab/app npm install node server.js
Puoi terminare il server in qualsiasi momento con Ctrl-c.
Apri il browser e vai all'indirizzo localhost:8081/.
Nota:annulla la registrazione di tutti i service worker e svuota tutte le cache dei service worker per localhost in modo che non interferiscano con il lab. In Chrome DevTools, puoi farlo facendo clic su Cancella dati sito nella sezione Cancella spazio di archiviazione della scheda Applicazione.
Apri la cartella service-worker-lab/app/ nell'editor di testo che preferisci. La cartella app/ è quella in cui creerai il lab.
Questa cartella contiene:
below/another.html,js/another.js,js/other.jseother.htmlsono risorse di esempio che utilizziamo per sperimentare l'ambito del service worker- La cartella
styles/contiene i fogli di stile CSS per questo lab - La cartella
test/contiene file per testare i tuoi progressi index.htmlè la pagina HTML principale del nostro sito/applicazione di esempioservice-worker.jsè il file JavaScript utilizzato per creare il service workerpackage.jsonepackage-lock.jsonmonitorano i pacchetti di nodi utilizzati in questo progettoserver.jsè un semplice server Express 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 nel service worker.
Apri index.html nell'editor di testo.
All'interno dei tag <script>, aggiungi il seguente codice 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 ⌘ + Opzione + I su Mac), facendo clic sulla scheda Applicazione e poi sull'opzione Service worker. Dovresti visualizzare un risultato simile al seguente:

(Facoltativo) Apri il sito su un browser non supportato e verifica che il controllo condizionale del supporto funzioni.
Spiegazione
Il codice precedente registra il file service-worker.js come service worker. Innanzitutto, verifica se il browser supporta i service worker. Questa operazione deve essere eseguita ogni volta che registri un service worker perché alcuni browser potrebbero non supportarli. Il codice registra quindi il service worker utilizzando il metodo register dell'API ServiceWorkerContainer, contenuto nell'interfaccia Navigator della finestra.
navigator.serviceWorker.register(...) restituisce una promessa che viene risolta con un oggetto registration una volta registrato correttamente il service worker. Se la registrazione non va a buon fine, la promessa verrà rifiutata.
Le modifiche allo stato del service worker attivano eventi nel service worker.
Aggiungere listener di eventi
Apri service-worker.js nell'editor di testo.
Aggiungi i seguenti listener di eventi al 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 non essere in ordine rispetto agli altri log (installazione e attivazione). Il service worker viene eseguito contemporaneamente alla pagina, pertanto 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). L'installazione, l'attivazione e altri eventi del service worker si verificano in un ordine definito all'interno del service worker e devono sempre essere visualizzati nell'ordine previsto.
Spiegazione
Il service worker genera un evento install al termine della registrazione. Nel codice precedente, un messaggio viene registrato all'interno del listener di eventi install, ma in un'app reale questo sarebbe un buon punto per memorizzare nella cache gli asset statici.
Quando viene registrato un service worker, il browser rileva se è nuovo (perché è diverso dal service worker installato in precedenza o perché non è presente alcun service worker registrato per questo sito). Se il service worker è nuovo (come in questo caso), il browser lo installa.
Il service worker genera un evento activate quando prende il controllo della pagina. Il codice riportato sopra registra un messaggio qui, ma questo evento viene spesso utilizzato per aggiornare le cache.
Per un determinato ambito può essere attivo un solo service worker alla volta (vedi Esplorazione dell'ambito del service worker), quindi un service worker appena installato non viene attivato finché quello esistente non viene più utilizzato. Per questo motivo, 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, il nuovo service worker è stato attivato immediatamente.
Nota:il semplice aggiornamento della pagina non è sufficiente per trasferire il controllo a un nuovo service worker, perché la nuova pagina verrà richiesta prima che la pagina corrente venga scaricata e non ci sarà un momento in cui il vecchio service worker non è in uso.
Nota:puoi anche attivare manualmente un nuovo service worker utilizzando lo strumento per sviluppatori di alcuni browser e in modo programmatico con skipWaiting(), come descritto nella sezione 3.4.
Aggiornare il service worker
Aggiungi il seguente commento in un punto qualsiasi di service-worker.js:
// I'm a new service workerSalva il file e aggiorna la pagina. Esamina i log nella console. Nota che il nuovo service worker viene installato, ma non attivato. In Chrome, puoi visualizzare il service worker in attesa nella scheda Applicazione di DevTools.

Chiudi tutte le pagine associate al service worker. Poi, riapri localhost:8081/. Il log della console dovrebbe indicare che il nuovo service worker è stato attivato.
Nota:se ottieni risultati imprevisti, assicurati che la cache HTTP sia disattivata negli strumenti per sviluppatori.
Spiegazione
Il browser rileva una differenza di byte tra il file service worker nuovo ed esistente (a causa del commento aggiunto), quindi viene 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 viene attivato finché il service worker esistente non viene più utilizzato. Chiudendo tutte le pagine sotto il controllo del service worker precedente, possiamo attivare il nuovo service worker.
Saltare la fase di attesa
È possibile che un nuovo service worker si attivi 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. Tieni presente che il nuovo service worker viene installato e attivato immediatamente, anche se un service worker precedente era in controllo.
Spiegazione
Il metodo skipWaiting() consente a un service worker di attivarsi al termine dell'installazione. Il listener di eventi di installazione è un punto comune in cui inserire la chiamata skipWaiting(), ma può essere chiamato ovunque durante o prima della fase di attesa. Per saperne di più su quando e come utilizzare skipWaiting(), consulta questa documentazione. Per il resto del lab, ora possiamo testare il nuovo codice del service worker senza annullarne manualmente la registrazione.
Per ulteriori informazioni
I service worker possono fungere da proxy tra la tua app web e la rete.
Aggiungiamo un listener di recupero per intercettare le richieste dal nostro dominio.
Aggiungi il codice seguente 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 di nuovo la console. Questa volta dovresti visualizzare gli eventi di recupero per la pagina e i relativi asset (come CSS).
Fai clic sui link Altra pagina, Un'altra pagina e Indietro.
Nella console vedrai gli eventi di recupero per ogni pagina e i relativi asset. Tutti i log hanno senso?
Nota:se visiti una pagina e la cache HTTP non è disattivata, 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 di recupero per ogni richiesta HTTP effettuata dal browser che rientra nel suo ambito. L'oggetto fetch event 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 nella console (in pratica potremmo anche creare e restituire la nostra risposta personalizzata con risorse arbitrarie).
Perché non è stato registrato alcun evento di recupero al primo aggiornamento? Per impostazione predefinita, il recupero degli eventi da una pagina non passa attraverso un service worker, a meno che la richiesta di pagina stessa non sia passata attraverso un service worker. In questo modo, il sito è coerente: se una pagina viene caricata senza il service worker, lo stesso vale per le relative risorse secondarie.
Per ulteriori informazioni
Codice della soluzione
Per ottenere una copia del codice funzionante, vai alla cartella 04-intercepting-network-requests/.
I service worker hanno un ambito. L'ambito del service worker determina da quali percorsi il service worker intercetta le richieste.
Trovare 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() viene risolta nell'oggetto di registrazione, che contiene l'ambito del service worker.
L'ambito predefinito è il percorso del file service worker e si estende a tutte le directory di livello inferiore. Pertanto, un service worker nella directory principale di un'app controlla le richieste di tutti i file dell'app.
Spostare il 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 del service worker corrente 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 Applicazione di DevTools:

Nella pagina principale, fai clic su Altra pagina, Un'altra pagina e Indietro. Quali richieste di recupero vengono registrate? Quali no?
Spiegazione
L'ambito predefinito del service worker è il percorso del file del service worker. Poiché il file service worker si trova ora 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 nell'ambito del service worker.
Impostare un ambito arbitrario
Sposta il service worker nella directory principale 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 sulla 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.
Anche in questo caso la console mostra che l'ambito del service worker è ora http://localhost:8081/below/ e registra gli eventi di recupero solo per another.html, another.css e another.js.
Spiegazione
È possibile impostare un ambito arbitrario passando 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 in /kitten/ e /kitten/lower/, ma non da pagine come /kitten o /.
Nota:non puoi impostare un ambito arbitrario superiore alla posizione effettiva del service worker. Tuttavia, se il service worker è attivo su un client servito con l'intestazione Service-Worker-Allowed, puoi specificare un ambito massimo per il service worker sopra la posizione del service worker.
Per ulteriori informazioni
Codice della soluzione
Per ottenere una copia del codice funzionante, vai alla cartella solution/.
Ora hai un service worker semplice in esecuzione e comprendi il ciclo di vita del service worker.
Per ulteriori informazioni
Per visualizzare tutti i codelab del corso di formazione sulle PWA, consulta il codelab di benvenuto del corso.