⚡ Prestazioni web

Back/forward cache: pagine istantanee con i tasti Indietro e Avanti

Come funziona la bfcache del browser, quali abitudini di codice la bloccano e come verificare che le pagine del sito vengano ripristinate all'istante.

Una buona parte delle navigazioni su un sito avviene con i tasti Indietro e Avanti: si apre una scheda prodotto, si torna all'elenco, se ne apre un'altra. Se ogni ritorno costringe il browser a scaricare, analizzare ed eseguire di nuovo la pagina, l'utente paga ogni volta il prezzo pieno del caricamento. La back/forward cache, abbreviata in bfcache, elimina questo costo: conserva in memoria l'intera pagina, compreso lo stato JavaScript, e la ripristina in pochi millisecondi.

È una delle ottimizzazioni con il miglior rapporto tra sforzo e risultato, perché non richiede di scrivere nuovo codice: basta non impedirla.

Come funziona

Quando l'utente lascia una pagina, il browser invece di distruggerla la "congela": sospende i timer, mette in pausa l'esecuzione degli script e tiene in memoria il DOM e l'heap JavaScript. Se l'utente torna indietro, la pagina viene "scongelata" esattamente com'era, con lo scroll nella stessa posizione, i campi dei moduli compilati e le variabili intatte.

È una cosa diversa dalla cache HTTP. La cache HTTP evita di riscaricare i file, ma la pagina deve comunque essere ricostruita: HTML analizzato, CSS applicato, script eseguiti. La bfcache salta tutto questo, ed è per questo che il ritorno appare istantaneo.

Cosa impedisce il ripristino

Il browser rinuncia a mettere una pagina in bfcache quando teme che congelarla possa rompere qualcosa. Le cause più frequenti sono:

  1. gestori dell'evento unload: sono il motivo classico. Il browser non può garantire che unload venga eseguito se la pagina è conservata, e in diversi casi preferisce escluderla;
  2. intestazione Cache-Control: no-store sul documento HTML: indica che la pagina non deve essere conservata e, a seconda del browser, può escluderla dalla bfcache;
  3. connessioni aperte al momento dell'uscita, come WebSocket, WebRTC o richieste ancora in corso, che il browser non sa come sospendere;
  4. finestre aperte con window.opener che mantengono un riferimento reciproco tra pagine;
  5. API particolari in uso, come alcune funzioni di accesso a dispositivi.

Molti di questi blocchi arrivano da script di terze parti: un widget di chat che apre un WebSocket o una libreria di analytics che registra un gestore unload possono escludere tutte le pagine del sito.

Sostituire unload con pagehide

L'evento unload era usato per inviare dati all'uscita, per esempio una statistica di sessione. Ma è inaffidabile anche senza considerare la bfcache: sui dispositivi mobili spesso non viene eseguito affatto, perché il sistema chiude la scheda senza preavviso.

Le alternative corrette sono:

  • pagehide, che scatta quando la pagina viene lasciata, sia che finisca in bfcache sia che venga distrutta;
  • visibilitychange con stato hidden, che scatta anche quando l'utente passa a un'altra app ed è il momento più affidabile per inviare dati.
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/statistiche', JSON.stringify(datiSessione));
  }
});

sendBeacon accoda la richiesta in modo che venga completata anche se la pagina viene chiusa subito dopo.

Gestire il ritorno dalla bfcache

Una pagina ripristinata non riceve un nuovo evento load, e questo può sorprendere. Se il codice aggiorna qualcosa solo al caricamento, per esempio il numero di articoli nel carrello, dopo un ritorno potrebbe mostrare dati vecchi. Per intercettare il ripristino si usa pageshow con la proprietà persisted:

window.addEventListener('pageshow', (evento) => {
  if (evento.persisted) {
    aggiornaCarrello();
    registraVisualizzazione();
  }
});

Allo stesso modo, se apri connessioni durature, chiudile in pagehide e riaprile in pageshow: in questo modo non bloccano la bfcache e la pagina resta funzionante dopo il ritorno.

Dati sensibili

Per le pagine con informazioni personali, come un'area riservata dopo il logout, il timore è che il tasto Indietro mostri dati che non dovrebbero più essere visibili. La soluzione più pulita non è vietare la bfcache, ma controllare lo stato di autenticazione nel gestore pageshow e, se la sessione è terminata, ricaricare o reindirizzare. Così si protegge l'utente senza rinunciare alla velocità sul resto del sito.

Verificare con gli strumenti

Chrome DevTools offre un test dedicato nel pannello Application, alla voce Back/forward cache. Premendo il pulsante di test, il browser naviga altrove e torna indietro, poi riporta se la pagina è stata ripristinata e, in caso contrario, l'elenco dei motivi. I motivi sono divisi in categorie: quelli risolvibili dallo sviluppatore, quelli in attesa di supporto da parte del browser e quelli non risolvibili.

Anche Lighthouse include un controllo che segnala le pagine escluse dalla bfcache. Per i dati reali, Chrome espone sulle voci di navigazione la proprietà notRestoredReasons, che permette di raccogliere dagli utenti veri i motivi del mancato ripristino.

Sintomo Causa probabile Intervento
Ritorno lento su tutte le pagine Script con unload Passare a pagehide o visibilitychange
Escluse solo le pagine con la chat WebSocket aperto Chiuderlo in pagehide, riaprirlo in pageshow
Escluse le pagine dinamiche no-store sull'HTML Valutare no-cache o private
Dati vecchi dopo il ritorno Logica legata a load Aggiornare in pageshow con persisted

In sintesi

  • La bfcache conserva in memoria la pagina intera e la ripristina all'istante con Indietro e Avanti.
  • Il nemico principale è l'evento unload: sostituiscilo con pagehide o visibilitychange.
  • Usa pageshow con persisted per aggiornare i dati dopo un ripristino.
  • Chiudi connessioni aperte all'uscita e riaprile al ritorno.
  • Verifica con il test di DevTools e raccogli i motivi dagli utenti reali.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica, unisce il rigore dell'analisi tecnica all'attenzione per le persone che usano la tecnologia.

Leggi anche