Gestione delle richieste di navigazione

Rispondere alle richieste di navigazione senza attendere sulla rete utilizzando un service worker.

Le richieste di navigazione sono richieste di documenti HTML effettuate dal browser ogni volta che inserisci un nuovo URL nella barra di navigazione o segui un link in una pagina che rimanda a un nuovo URL. È qui che i service worker fanno il loro maggiore impatto sulle prestazioni: se utilizzi un service worker per rispondere alle richieste di navigazione senza attendere la rete, puoi garantire che le navigazioni siano affidabili e veloci, oltre che resilienti quando la rete non è disponibile. Questa è la migliore soluzione in termini di prestazioni derivante da un service worker rispetto a quanto ottenibile con la memorizzazione nella cache HTTP.

Come descritto nella guida Identificare le risorse caricate dalla rete, una richiesta di navigazione è la prima di molte richieste effettuate nella "cascata" del traffico di rete. Il codice HTML caricato tramite una richiesta di navigazione avvia il flusso di tutte le altre richieste per le risorse secondarie come immagini, script e stili.

All'interno del gestore di eventi fetch di un service worker, puoi determinare se una richiesta è una navigazione controllando la proprietà request.mode nella FetchEvent. Se è impostato su 'navigate', si tratta di una richiesta di navigazione.

Come regola generale, non utilizzare Cache-Control headers di lunga durata per memorizzare nella cache la risposta HTML per una richiesta di navigazione. Normalmente dovrebbero essere soddisfatti tramite la rete, con Cache-Control: no-cache, per garantire che il codice HTML, insieme alla catena di richieste di rete successive, sia (ragionevolmente) aggiornato. Andare alla rete ogni volta che l'utente passa a una nuova pagina significa purtroppo che ogni navigazione potrebbe essere lenta. Quanto meno, significa che non sarà affidabile veloce.

Diversi approcci per le architetture

Capire come rispondere alle richieste di navigazione evitando al tempo stesso la rete può essere difficoltoso. L'approccio giusto dipende molto dall'architettura del tuo sito web e dal numero di URL univoci a cui gli utenti possono accedere.

Sebbene non esistano soluzioni uniche, le seguenti linee guida generali dovrebbero aiutarti a decidere qual è l'approccio più fattibile.

Siti statici di piccole dimensioni

Se la tua app web è costituita da un numero relativamente ridotto di URL univoci (un paio di dozzine) e ognuno di questi URL corrisponde a un file HTML statico diverso, un approccio attuabile consiste nel memorizzare tutti questi file HTML nella cache e rispondere alle richieste di navigazione con l'HTML relativo alla cache appropriato.

Utilizzando la precauzione nella cache, puoi memorizzare in anticipo la cache HTML non appena il service worker viene installato e aggiornare il codice HTML memorizzato nella cache ogni volta che ricrei il sito ed esegui nuovamente il deployment del service worker.

In alternativa, se preferisci evitare di memorizzare nella cache tutto il codice HTML, magari perché gli utenti tendono a visitare solo un sottoinsieme di URL sul tuo sito, puoi utilizzare una strategia di memorizzazione nella cache di runtime stale-while-revalidate. Tuttavia, fai attenzione a questo approccio, poiché ogni singolo documento HTML viene memorizzato nella cache e aggiornato separatamente. L'utilizzo della memorizzazione nella cache di runtime per l'HTML è la soluzione più appropriata se hai un numero ridotto di URL che vengono rivisitati frequentemente dallo stesso insieme di utenti e se sei sicuro che questi URL vengano riconvalidati in modo indipendente l'uno dall'altro.

App con una sola pagina

Le moderne applicazioni web utilizzano spesso un'architettura a pagina singola. al suo interno, il codice JavaScript lato client modifica il codice HTML in risposta alle azioni degli utenti. Questo modello utilizza l'API History per modificare l'URL corrente quando l'utente interagisce con l'app web, portando a quella che è effettivamente una navigazione "simulata". Anche se le navigazioni successive potrebbero essere "fasulle", la navigazione iniziale è reale ed è comunque importante assicurati che non sia bloccata sulla rete.

Fortunatamente, se utilizzi l'architettura a pagina singola, c'è un semplice pattern da seguire per gestire la navigazione iniziale dalla cache: la shell dell'applicazione. In questo modello, il service worker risponde alle richieste di navigazione restituendo lo stesso file HTML singolo che è già stato prememorizzato nella cache, indipendentemente dall'URL richiesto. Questo codice HTML dovrebbe essere essenziale, ad esempio costituito da un indicatore di caricamento generico o da uno scheletro di contenuti. Una volta che il browser ha caricato questo codice HTML dalla cache, il codice JavaScript lato client esistente prende il controllo e restituisce i contenuti HTML corretti per l'URL dalla richiesta di navigazione originale.

Workbox fornisce gli strumenti necessari per implementare questo approccio; navigateFallback option ti consente di specificare il documento HTML da utilizzare come shell dell'app, oltre a un elenco facoltativo di autorizzazione e rifiuto per limitare questo comportamento a un sottoinsieme dei tuoi URL.

App con più pagine

Se il server web genera il codice HTML del tuo sito in modo dinamico o se hai più di una decina di pagine uniche, è molto più difficile evitare la rete quando si gestiscono le richieste di navigazione. È probabile che il consiglio nella sezione Tutto il resto sia valido per te.

Tuttavia, per un determinato sottoinsieme di app con più pagine, potresti essere in grado di implementare un service worker che replica completamente la logica utilizzata nel tuo server web per generare il codice HTML. Questa soluzione funziona al meglio se puoi condividere informazioni di routing e modelli tra gli ambienti server e dei service worker e, in particolare, se il tuo server web utilizza JavaScript (senza fare affidamento sulle funzionalità specifiche di Node.js, come l'accesso al file system).

Se il tuo server web rientra in questa categoria e vuoi esplorare un approccio per spostare la generazione HTML dalla rete al tuo service worker, puoi iniziare consultando le indicazioni riportate in Oltre le SPA: architetture alternative per la tua PWA.

Tutto il resto

Se non riesci a rispondere alle richieste di navigazione con codice HTML memorizzato nella cache, devi adottare le misure necessarie per assicurarti che l'aggiunta di un service worker al sito (per gestire altre richieste non HTML) non rallenti le tue navigazioni. L'avvio del service worker senza utilizzarlo per rispondere a una richiesta di navigazione introdurrà una piccola quantità di latenza (come spiegato in Creazione di app più rapide e più resilienti con Service Worker). Puoi mitigare questo overhead attivando una funzionalità chiamata precaricamento della navigazione e poi utilizzando la risposta di rete precaricata all'interno del gestore di eventi fetch.

Workbox fornisce una libreria di supporto che rileva se il precaricamento di navigazione è supportato e, in tal caso, semplifica il processo di utilizzo della risposta di rete da parte del service worker.

Foto di Aaron Burden su Unsplash