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, posticipare la registrazione del service worker fino al caricamento della pagina iniziale offre la migliore esperienza agli utenti, in particolare a quelli che utilizzano 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. Tuttavia, si tratta solo di piccole variazioni rispetto alle poche righe di codice standard.
Quindi, ci sono sfumature per 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. Qualsiasi elemento che rallenti il recupero di queste risposte è nemico di un'esperienza interattiva rapida.
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 spendere 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? Qualsiasi dubbio sulla contesa della CPU o della memoria dovrebbe essere superato dalle preoccupazioni relative alla larghezza di banda limitata disponibile su 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 presenta una breve animazione prima della transizione 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 che impatto ha la registrazione ritardata dei worker di servizio 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 era già in esecuzione prima di visitare una pagina, non avrebbe avuto 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
comando senza esecuzione durante le visite successive. Il momento in cui viene chiamato non è rilevante.
Motivi per registrarsi in anticipo
Esistono scenari in cui ha senso registrare il tuo worker di servizio il prima possibile? Un esempio che mi viene in mente è 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 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 sopra riflette il traffico di rete quando il sample è 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, generate dall'handler install
del service worker)
intersecate con le richieste per le altre risorse necessarie per visualizzare la pagina.
Nello screenshot riportato sopra, la registrazione del service worker è stata ritardata fino al caricamento della pagina. Puoi notare che le richieste di precaching non iniziano finché tutte le risorse non sono state recuperate dalla rete, eliminando qualsiasi contesa 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 extra se esegui questo tipo di test da un dispositivo di fascia bassa reale 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
In sintesi, assicurarti che i tuoi utenti abbiano la migliore esperienza possibile alla 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');
});
}