Best practice per la scelta del momento della registrazione del service worker.
I service worker possono velocizzare in modo significativo le visite ripetute alla tua app web, ma devi adottare misure per assicurarti che l'installazione iniziale di un service worker non peggiori l'esperienza di prima visita dell'utente.
In genere, rinviare la registrazione dei service worker fino al termine del caricamento della pagina iniziale offre la migliore esperienza agli utenti, in particolare quelli su dispositivi mobili con connessioni di rete più lente.
Boilerplate di registrazione comune
Se hai mai letto qualcosa sui worker di servizio, probabilmente hai trovato del codice boilerplate sostanzialmente simile al seguente:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
A volte, questo messaggio potrebbe essere accompagnato da alcune istruzioni console.log()
o da codice che rileva un aggiornamento di una registrazione di service worker precedente, per informare gli utenti di aggiornare la pagina. Ma queste sono solo piccole variazioni
delle poche righe di codice standard.
C'è qualche sfumatura in navigator.serviceWorker.register
? Esistono delle best practice da seguire? Non sorprende (dato che questo articolo non termina
qui), la risposta a entrambe è "sì".
La prima visita di un utente
Prendiamo in considerazione la prima visita di un utente a un'app web. Non è ancora presente alcun servizio worker e il browser non ha modo di sapere in anticipo se verrà eventualmente installato un servizio worker.
In qualità di sviluppatore, la tua priorità dovrebbe essere assicurarti che il browser riceva rapidamente l'insieme minimo di risorse fondamentali necessarie per visualizzare una pagina interattiva. Tutto ciò che rallenta il recupero di queste risposte è nemico di un'esperienza time-to-interattiva veloce.
Ora immagina che durante il download del codice JavaScript o delle immagini necessarie per il rendering della pagina, il browser decida di avviare un thread o un processo in background (per brevità, assumeremo che si tratti di un thread). Supponiamo che non utilizzi un computer desktop potente, ma il tipo di cellulare sottodimensionato che gran parte del mondo considera il proprio dispositivo principale. L'avvio di questo thread aggiuntivo aggiunge contese per il tempo della CPU e la memoria che il browser potrebbe altrimenti impiegare per il rendering di una pagina web interattiva.
È improbabile che un thread in background inattivo faccia una differenza significativa. Ma cosa succede se il thread non è inattivo, ma decide di iniziare anche a scaricare risorse dalla rete? Eventuali preoccupazioni relative alla CPU o alla memoria dovrebbero preoccuparsi della larghezza di banda limitata disponibile per molti dispositivi mobili. La larghezza di banda è preziosa, quindi non minare le risorse critiche scaricando contemporaneamente risorse secondarie.
Tutto ciò significa che l'avvio di un nuovo thread di worker di servizio per scaricare e memorizzare nella cache le risorse in background può andare contro il tuo obiettivo di fornire l'esperienza più breve possibile la prima volta che un utente visita il tuo sito.
Migliorare il testo standard
La soluzione è controllare l'avvio del service worker scegliendo quando chiamare
navigator.serviceWorker.register()
. Una semplice regola empirica consiste nel ritardare la registrazione fino a dopo l'attivazione di load
event
il giorno window
, come segue:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}
Tuttavia, il momento giusto per avviare la registrazione del servizio worker può dipendere anche da cosa fa la tua app web subito dopo il caricamento. Ad esempio, l'app web Google I/O 2016 mostra una breve animazione prima di passare alla schermata principale. Il nostro team ha rilevato che l'avvio della registrazione del servizio worker durante l'animazione potrebbe causare problemi su dispositivi mobili di fascia bassa. Anziché offrire agli utenti un'esperienza negativa, abbiamo ritardo la registrazione del servizio worker fino al termine dell'animazione, quando il browser aveva maggiori probabilità di avere alcuni secondi di inattività.
Analogamente, se la tua app web utilizza un framework che esegue una configurazione aggiuntiva dopo il caricamento della pagina, cerca un evento specifico del framework che segnali quando l'operazione è completata.
Visite successive
Finora ci siamo concentrati sull'esperienza della prima visita, ma quale impatto ha il ritardo della registrazione dei service worker sulle visite ripetute al tuo sito? Anche se potrebbe sorprendere alcune persone, non dovrebbe esserci alcun impatto.
Quando un service worker viene registrato, passa attraverso gli eventi di ciclo di vita install
e activate
.
Una volta attivato, un service worker può gestire gli eventi fetch
per tutte le visite successive alla tua app web. Il service worker si avvia prima della richiesta di qualsiasi pagina nel suo ambito, il che è logico. Se il service worker esistente non fosse già in esecuzione prima di visitare una pagina, non avrebbe la possibilità di soddisfare gli eventi fetch
per le richieste di navigazione.
Pertanto, una volta che è presente un worker di servizio attivo, non importa quando chiami
navigator.serviceWorker.register()
o, in effetti, se lo chiami.
A meno che non modifichi l'URL dello script del worker di servizio,
navigator.serviceWorker.register()
è effettivamente un'operazione nulla durante le visite successive. Quando viene chiamato è irrilevante.
Motivi per registrarsi in anticipo
Esistono scenari in cui è consigliabile registrare il tuo worker di servizio il prima possibile? Un esempio è quando il tuo worker dei servizi utilizza
clients.claim()
per assumere il controllo della pagina durante la prima visita e il worker dei servizi
esegue in modo aggressivo la memorizzazione nella cache di runtime
all'interno del suo gestore fetch
. In questa situazione, è utile attivare il servizio worker il più rapidamente possibile per provare a compilare le relative cache di runtime con risorse che potrebbero essere utili in un secondo momento. Se la tua app web rientra in questa categoria, vale la pena fare un passo indietro per assicurarti che l'handler install
del tuo service worker non richieda risorse che competono per la larghezza di banda con le richieste della pagina principale.
Provare
Un ottimo modo per simulare una prima visita è aprire l'app web in una finestra di Chrome in incognito e controllare il traffico di rete in Chrome DevTools. In qualità di sviluppatore web, probabilmente ricarichi un'istanza locale della tua app web decine e decine di volte al giorno. Tuttavia, se visiti di nuovo il tuo sito quando è già presente un servizio worker e le cache sono completamente compilate, non avrai la stessa esperienza di un nuovo utente ed è facile ignorare un potenziale problema.
Ecco un esempio che illustra la differenza che può fare il momento della registrazione. Entrambi gli screenshot sono stati acquisiti durante la visita a un'app di esempio in modalità di navigazione in incognito utilizzando la limitazione della rete per simulare una connessione lenta.
Lo screenshot riportato sopra mostra il traffico di rete quando il campione è stato modificato
per eseguire la registrazione del service worker il prima possibile. Puoi vedere le richieste di precaching (le voci con l'icona a forma di ingranaggio accanto, originate dall'handler install
del service worker) alternate alle richieste per le altre risorse necessarie per visualizzare la pagina.
Nello screenshot precedente, la registrazione dei service worker è stata ritardata fino al caricamento della pagina. Puoi notare che le richieste di pre-memorizzazione nella cache non iniziano finché tutte le risorse non sono state recuperate dalla rete, eliminando qualsiasi conflitto per la larghezza di banda. Inoltre, poiché alcuni degli elementi che stiamo precaricando sono già nella cache HTTP del browser (gli elementi con (from disk cache)
nella colonna Dimensioni), possiamo compilare la cache del service worker senza dover accedere di nuovo alla rete.
Punti bonus se esegui questo tipo di test da un dispositivo effettivo di fascia bassa su una rete mobile reale. Puoi sfruttare le funzionalità di debugging remoto di Chrome per collegare uno smartphone Android al tuo computer tramite USB e assicurarti che i test che stai eseguendo riflettano effettivamente l'esperienza reale di molti dei tuoi utenti.
Conclusione
Riassumendo, assicurarsi che gli utenti abbiano la migliore esperienza di prima visita dovrebbe essere una priorità assoluta. Ritardare la registrazione del service worker fino al caricamento della pagina durante la visita iniziale può contribuire a garantire questo risultato. Continuerai a usufruire di tutti i vantaggi di un servizio worker per le tue visite ripetute.
Un modo semplice per ritardare la registrazione iniziale del tuo service worker fino al caricamento della prima pagina è utilizzare quanto segue:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}