Service worker più aggiornati per impostazione predefinita

tl;dr

A partire da Chrome 68, le richieste HTTP che verificano la presenza di aggiornamenti dello script del service worker non non deve essere soddisfatta dalla cache HTTP per impostazione predefinita. Questa operazione risolve un problema comune degli sviluppatori: in cui l'impostazione di un'intestazione Cache-Control involontaria nello script del service worker potrebbe agli aggiornamenti in ritardo.

Se hai già disattivato la memorizzazione nella cache HTTP per il tuo script /service-worker.js pubblicandolo con Cache-Control: max-age=0, non dovresti notare alcuna modifica a causa della nuova impostazione predefinita comportamento degli utenti.

Inoltre, a partire da Chrome 78, il confronto byte per byte verrà applicati a script caricati in un service worker importScripts() Qualsiasi modifica apportata a uno script importato attiverà flusso di aggiornamento dei Service worker, proprio come farebbe una modifica al service worker di primo livello.

Sfondo

Ogni volta che accedi a una nuova pagina che rientra nell'ambito di un service worker, richiama esplicitamente registration.update() da JavaScript o quando un service worker viene "risveglio" tramite un evento push o sync, il browser richiederà, in parallelo, la risorsa JavaScript che è stata originariamente passata al navigator.serviceWorker.register(), per cercare aggiornamenti allo script del service worker.

Ai fini di questo articolo, supponiamo che il suo URL sia /service-worker.js e che contiene una singola chiamata a importScripts(), che carica codice aggiuntivo eseguito all'interno del service worker:

// Inside our /service-worker.js file:
importScripts('path/to/import.js');

// Other top-level code goes here.

Cosa cambierà?

Prima di Chrome 68, la richiesta di aggiornamento di /service-worker.js veniva effettuata tramite la cache HTTP (come accade nella maggior parte dei recuperi). Questo significava che se lo script era stato originariamente inviato con Cache-Control: max-age=600, gli aggiornamenti entro i successivi 600 secondi (10 minuti) non verrebbero inviati alla rete, quindi il l'utente potrebbe non ricevere la versione più aggiornata del service worker. Tuttavia, se max-age era maggiore di 86.400 (24 ore), viene trattato come se fosse 86.400, per evitare che gli utenti rimangano bloccati con una determinata versione per sempre.

A partire dalla versione 68, la cache HTTP verrà ignorata quando verranno richiesti aggiornamenti al service worker script, pertanto le applicazioni web esistenti potrebbero notare un aumento della frequenza delle richieste per dello script del service worker. Le richieste per importScripts verranno comunque inviate tramite la cache HTTP. Ma questo è solo l'impostazione predefinita. È disponibile una nuova opzione di registrazione, updateViaCache, che offre il controllo questo comportamento.

updateViaCache

Ora gli sviluppatori possono passare una nuova opzione quando chiamano navigator.serviceWorker.register(): il parametro updateViaCache. Può assumere uno dei tre valori seguenti: 'imports', 'all' o 'none'.

I valori determinano se e come la cache HTTP standard del browser entra in gioco quando si effettua una richiesta HTTP per verificare la presenza di risorse dei service worker aggiornate.

  • Se il criterio viene impostato su 'imports', la cache HTTP non verrà mai consultata durante il controllo della disponibilità di aggiornamenti del /service-worker.js script, ma verrà consultato durante il recupero degli script importati (nel nostro esempio path/to/import.js). Questa è l'impostazione predefinita e corrisponde al comportamento a partire dal giorno in Chrome 68.

  • Se il criterio viene impostato su 'all', la cache HTTP verrà consultata quando si effettuano richieste sia per il script /service-worker.js di primo livello, nonché tutti gli script importati all'interno del servizio come path/to/import.js. Questa opzione corrisponde al comportamento precedente in Chrome, precedenti a Chrome 68.

  • Se impostato su 'none', la cache HTTP non verrà consultata quando si effettuano richieste per il /service-worker.js di primo livello o per qualsiasi script importato, come l'ipotetico path/to/import.js.

Ad esempio, il seguente codice registrerà un service worker e assicura che la cache HTTP sia non è mai stato consultato durante il controllo di aggiornamenti dello script /service-worker.js o di eventuali script a cui viene fatto riferimento tramite importScripts() all'interno di /service-worker.js:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {
    updateViaCache: 'none',
    // Optionally, set 'scope' here, if needed.
  });
}

Verifica la presenza di aggiornamenti degli script importati

Prima di Chrome 78, qualsiasi script del service worker caricato tramite importScripts() deve essere recuperato solo una volta (verificando prima la cache HTTP o rete, a seconda della configurazione di updateViaCache). Successivamente, l'iniziale dei dati, verrebbero archiviate internamente dal browser e non verranno mai recuperate di nuovo.

L'unico modo per far sì che un service worker già installato riceva le modifiche a uno script importato modificava l'URL dello script, di solito aggiungendo uno script semver value (ad es. importScripts('https://example.com/v1.1.0/index.js')) o includendo un hash di i contenuti (ad es. importScripts('https://example.com/index.abcd1234.js')). R l'effetto collaterale della modifica dell'URL importato è che il service worker di primo livello dei contenuti dello script, a sua volta, attiva flusso di aggiornamento dei service worker.

A partire da Chrome 78, ogni volta che viene eseguito un controllo degli aggiornamenti per un del service worker, verranno effettuati contemporaneamente dei controlli per determinare se o non sono stati modificati i contenuti degli script importati. In base Cache-Control intestazioni utilizzate. Questi controlli degli script importati potrebbero essere completati da cache HTTP se updateViaCache è impostato su 'all' o 'imports' (ovvero il valore predefinito) oppure i controlli potrebbero andare direttamente sulla rete se Il valore di updateViaCache è impostato su 'none'.

Se un controllo degli aggiornamenti di uno script importato genera una differenza byte per byte rispetto a quanto archiviato in precedenza dal service worker, ma a sua volta attivare l'intero flusso di aggiornamento del service worker, anche se il servizio di primo livello mentre il file worker rimane lo stesso.

Il comportamento di Chrome 78 corrisponde a quello implemented da Firefox diversi anni fa, in Firefox 56. Safari implementa già questo comportamento beh.

Cosa devono fare gli sviluppatori?

Se hai disattivato efficacemente la memorizzazione nella cache HTTP per il tuo script /service-worker.js pubblicandolo con Cache-Control: max-age=0 (o un valore simile), non dovresti notare alcuna modifica a causa di il nuovo comportamento predefinito.

Se pubblichi lo script /service-worker.js con la memorizzazione nella cache HTTP abilitata, o poiché è solo l'impostazione predefinita per l'ambiente di hosting, potresti iniziare a vedere un aumento di richieste HTTP aggiuntive per /service-worker.js effettuate da del tuo server: si tratta di richieste che dovevano essere soddisfatte dalla cache HTTP. Se vuoi continua a consentire al valore dell'intestazione Cache-Control di influire sull'aggiornamento del tuo /service-worker.js, dovrai iniziare a impostare esplicitamente updateViaCache: 'all' quando della registrazione del Service worker.

Dato che ci può essere una long-tail di utenti che usano versioni meno recenti del browser, è comunque una buona idea continua a impostare l'intestazione HTTP Cache-Control: max-age=0 negli script dei service worker, anche se browser più recenti potrebbe ignorarli.

Gli sviluppatori possono sfruttare questa opportunità per decidere se attivare esplicitamente l'importazione fuori dalla memorizzazione nella cache HTTP e aggiungere updateViaCache: 'none' al proprio service worker la registrazione, se opportuno.

Pubblicazione di script importati

A partire da Chrome 78, gli sviluppatori potrebbero vedere più richieste HTTP in entrata per risorse caricate tramite importScripts(), poiché ora verranno controllate aggiornamenti.

Se desideri evitare questo traffico HTTP aggiuntivo, imposta Cache-Control intestazioni durante la pubblicazione di script che includono hash o semver in i relativi URL e si basano sul comportamento updateViaCache predefinito di 'imports'.

In alternativa, se vuoi che gli script importati vengano controllati frequentemente aggiornali, quindi assicurati di pubblicarli con Cache-Control: max-age=0, o che utilizzi updateViaCache: 'none'.

Per approfondire

"Il ciclo di vita dei service worker" e "Best practice per la memorizzazione nella cache e getchas di max-age", entrambi di Jake Archibald, sono consigliati a tutti gli sviluppatori che eseguono il deployment di qualsiasi cosa sul web.