Registrazione dei service worker

Best practice per la sincronizzazione della registrazione dei service worker.

I service worker possono velocizzare notevolmente le visite ripetute alla tua app web, ma devi adottare le misure necessarie per assicurarti che l'installazione iniziale di un service worker non comprometta l'esperienza della prima visita dell'utente.

In genere, rinviare la registrazione dei service worker fino al caricamento della pagina iniziale offrirà l'esperienza migliore agli utenti, in particolare quelli sui dispositivi mobili con connessioni di rete più lente.

boilerplate di registrazione comune

Se hai mai sentito parlare dei service worker, probabilmente ti sei imbattuto in un boilerplate sostanzialmente simile al seguente:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

A volte il problema potrebbe essere accompagnato da alcune istruzioni console.log() o codice che rileva un aggiornamento alla precedente registrazione di un service worker, per consentire agli utenti di aggiornare la pagina. Ma si tratta solo di piccole variazioni di poche righe di codice standard.

Quindi, ha qualche sfumatura in navigator.serviceWorker.register? Ci sono best practice da seguire? Non sorprende che (dato che l'articolo non termini qui), la risposta a entrambe le domande è "sì!"

La prima visita di un utente

Consideriamo la prima visita di un utente a un'app web. Non esiste ancora un service worker e il browser non ha modo di sapere in anticipo se alla fine verrà installato un service worker.

In qualità di sviluppatore, la tua priorità dovrebbe essere quella di assicurarti che il browser riceva rapidamente l'insieme minimo di risorse critiche necessarie per visualizzare una pagina interattiva. Tutto ciò che rallegra il recupero di queste risposte è il nemico di un'esperienza rapida all'interattività.

Ora immagina che, durante il download del codice JavaScript o delle immagini che devono essere visualizzate dalla pagina, il tuo browser decida di avviare un thread o un processo in background (per brevità, supponiamo che si tratti di un thread). Supponendo di non usare un computer desktop robusto, ma piuttosto il tipo di cellulare con prestazioni inferiori al previsto che la maggior parte del mondo considera il proprio dispositivo principale. L'avvio di questo thread aggiuntivo aggiunge una contesa per il tempo di CPU e la memoria che il tuo browser potrebbe altrimenti spendere per il rendering di una pagina web interattiva.

È improbabile che un thread in background inattivo faccia una differenza significativa. Cosa succede se quel thread non è inattivo, ma decide invece che inizierà anche a scaricare risorse dalla rete? Eventuali dubbi in merito a contese di CPU o memoria dovrebbero tornare in secondo piano per non preoccuparsi della larghezza di banda limitata disponibile per molti dispositivi mobili. La larghezza di banda è preziosa, pertanto non compromettere le risorse critiche scaricando contemporaneamente le risorse secondarie.

Tutto questo significa che l'avvio di un nuovo thread del service worker per scaricare le risorse e memorizzare nella cache le risorse in background può andare contro l'obiettivo di fornire l'esperienza interattiva più breve la prima volta che un utente visita il tuo sito.

Migliorare il boilerplate

La soluzione consiste nel controllare l'avvio del service worker scegliendo quando chiamare navigator.serviceWorker.register(). Una semplice regola generale è ritardare la registrazione fino all'attivazione dell'evento load event il giorno window, in questo modo:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

Tuttavia, il momento giusto per avviare la registrazione del service worker può anche dipendere da ciò che sta facendo la tua app web subito dopo il caricamento. Ad esempio, l'app web Google I/O 2016 presenta una breve animazione prima del passaggio alla schermata principale. Il nostro team ha rilevato che l'avvio della registrazione dei service worker durante l'animazione potrebbe causare problemi di qualità dei dispositivi mobili di fascia bassa. Anziché offrire agli utenti un'esperienza negativa, abbiamo ritardato la registrazione dei service worker fino al termine dell'animazione, data in cui è più probabile che il browser abbia qualche secondo di inattività.

Allo stesso modo, 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 il lavoro è stato completato.

Visite successive

Finora ci siamo concentrati sull'esperienza della prima visita, ma quale impatto ha la registrazione ritardata dei Service worker sulle visite ripetute al tuo sito? Sebbene possa sorprendere alcune persone, non dovrebbe avere alcun impatto.

Una volta registrato un service worker, questo partecipa agli eventi install e activate. Una volta attivato un service worker, può gestire gli eventi fetch per eventuali visite successive alla tua app web. Il service worker inizia prima che venga effettuata la richiesta relativa alle pagine nel suo ambito, il che ha senso quando ci pensi. 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.

Una volta che è presente un service worker attivo, non importa quando chiami navigator.serviceWorker.register() o addirittura se lo chiami. A meno che non modifichi l'URL dello script del service worker, navigator.serviceWorker.register() diventa di fatto no-op durante le visite successive. Quando viene chiamato, non è pertinente.

Motivi per registrarsi in anticipo

Ci sono scenari in cui ha senso registrare il service worker il prima possibile? Uno che ti viene in mente è quando il service worker utilizza clients.claim() per assumere il controllo della pagina durante la prima visita e esegue in modo aggressivo la memorizzazione nella cache del runtime all'interno del suo gestore fetch. In questa situazione, esiste il vantaggio di attivare il service worker il più rapidamente possibile, per provare a compilare le sue cache di runtime con risorse che potrebbero tornare utili in seguito. Se la tua app web rientra in questa categoria, vale la pena fare un passo indietro per assicurarti che il gestore install del service worker non richieda risorse che si contendono la larghezza di banda con le richieste della pagina principale.

Test dei prodotti

Un ottimo modo per simulare una prima visita è aprire l'app web in una finestra di navigazione in incognito di Chrome e controllare il traffico di rete in DevTools di Chrome. In qualità di sviluppatore web, probabilmente ricarichi un'istanza locale della tua applicazione web decine e decine di volte al giorno. Ma se visiti nuovamente il tuo sito quando è già presente un service worker e le cache completamente compilate, non ottieni la stessa esperienza che un nuovo utente otterrebbe ed è facile ignorare un potenziale problema.

Ecco un esempio che illustra la differenza che potrebbero fare i tempi di registrazione. Entrambi gli screenshot vengono acquisiti durante la visita di un'app di esempio in modalità di navigazione in incognito utilizzando la limitazione della rete per simulare una connessione lenta.

Traffico di rete con registrazione anticipata.

Lo screenshot in alto mostra il traffico di rete al momento della modifica dell'esempio per eseguire la registrazione dei service worker il prima possibile. Puoi vedere le richieste di precaricamento (le voci con accanto l'icona a forma di ingranaggio, provenienti dal gestore install del service worker) intersecate con richieste relative ad altre risorse necessarie per visualizzare la pagina.

Traffico di rete con registrazione tardiva.

Nello screenshot riportato sopra, la registrazione dei service worker è stata ritardata fino al caricamento della pagina. Puoi notare che le richieste di pre-memorizzazione nella cache non vengono avviate finché tutte le risorse non sono state recuperate dalla rete, eliminando qualsiasi contesa per la larghezza di banda. Inoltre, poiché alcuni degli elementi di cui stiamo eseguendo la pre-memorizzazione nella cache si trovano già nella cache HTTP del browser (gli elementi con (from disk cache) nella colonna Dimensione), possiamo popolare la cache del service worker senza dover accedere nuovamente alla rete.

Ricevi punti bonus se esegui questo tipo di test su un dispositivo reale di fascia bassa su una rete mobile reale. Puoi sfruttare le funzionalità di debug remoto di Chrome per collegare uno smartphone Android al computer tramite USB e assicurarti che i test in esecuzione riflettano l'esperienza reale di molti utenti.

Conclusione

Per riassumere, assicurati che gli utenti abbiano la migliore esperienza di prima visita dovrebbe essere la massima priorità. Posticipare la registrazione dei service worker fino al caricamento della pagina durante la visita iniziale può contribuire a garantirlo. Avrai comunque tutti i vantaggi di avere un service worker per le tue visite ripetute.

Un modo semplice per assicurarsi di ritardare la registrazione iniziale del service worker fino al caricamento della prima pagina consiste nell'utilizzare quanto segue:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}