API Page Lifecycle

Browser Support

  • Chrome: 68.
  • Edge: 79.
  • Firefox: not supported.
  • Safari: not supported.

I browser moderni a volte sospendono le pagine o le eliminano completamente quando le risorse di sistema sono limitate. In futuro, i browser vogliono farlo in modo proattivo, in modo da consumare meno energia e memoria. L'API Page Lifecycle fornisce hook del ciclo di vita in modo che le pagine possano gestire in sicurezza questi interventi del browser senza influire sull'esperienza utente. Dai un'occhiata all'API per vedere se devi implementare queste funzionalità nella tua applicazione.

Sfondo

Il ciclo di vita delle applicazioni è un modo fondamentale in cui i sistemi operativi moderni gestiscono le risorse. Su Android, iOS e le versioni recenti di Windows, le app possono essere avviate e interrotte in qualsiasi momento dal sistema operativo. In questo modo, queste piattaforme possono semplificare e riassegnare le risorse dove sono più utili per l'utente.

Sul web, storicamente non esiste un ciclo di vita di questo tipo e le app possono essere mantenute attive a tempo indeterminato. Con un numero elevato di pagine web in esecuzione, le risorse di sistema critiche come memoria, CPU, batteria e rete possono essere sovrascritte, il che comporta un'esperienza utente finale negativa.

Sebbene la piattaforma web abbia da tempo eventi correlati agli stati del ciclo di vita, come load, unload e visibilitychange, questi eventi consentono agli sviluppatori di rispondere solo alle modifiche dello stato del ciclo di vita avviate dall'utente. Affinché il web funzioni in modo affidabile su dispositivi a basso consumo energetico (e sia più attento alle risorse in generale su tutte le piattaforme), i browser hanno bisogno di un modo per recuperare e riallocare in modo proattivo le risorse di sistema.

Infatti, i browser di oggi adottano già misure attive per risparmiare risorse per le pagine nelle schede in background e molti browser (in particolare Chrome) vorrebbero fare molto di più per ridurre l'impronta complessiva delle risorse.

Il problema è che gli sviluppatori non hanno modo di prepararsi a questi tipi di interventi avviati dal sistema o addirittura di sapere che si stanno verificando. Ciò significa che i browser devono essere conservativi o rischiano di danneggiare le pagine web.

L'API Page Lifecycle tenta di risolvere questo problema:

  • Introduzione e standardizzazione del concetto di stati del ciclo di vita sul web.
  • Definizione di nuovi stati avviati dal sistema che consentono ai browser di limitare le risorse che possono essere utilizzate da schede nascoste o inattive.
  • Creazione di nuove API ed eventi che consentono agli sviluppatori web di rispondere alle transizioni verso e da questi nuovi stati avviati dal sistema.

Questa soluzione offre la prevedibilità di cui gli sviluppatori web hanno bisogno per creare applicazioni resilienti agli interventi del sistema e consente ai browser di ottimizzare in modo più aggressivo le risorse di sistema, a vantaggio di tutti gli utenti web.

Il resto di questo post introdurrà le nuove funzionalità del ciclo di vita della pagina e analizzerà la loro relazione con tutti gli stati e gli eventi della piattaforma web esistenti. Fornirà inoltre consigli e best practice sui tipi di lavoro che gli sviluppatori devono (e non devono) svolgere in ogni stato.

Panoramica degli stati e degli eventi del ciclo di vita della pagina

Tutti gli stati del ciclo di vita della pagina sono discreti e reciprocamente esclusivi, il che significa che una pagina può trovarsi in un solo stato alla volta. La maggior parte delle modifiche allo stato del ciclo di vita di una pagina sono generalmente osservabili tramite gli eventi DOM (per le eccezioni, consulta i consigli per gli sviluppatori per ogni stato).

Forse il modo più semplice per spiegare gli stati del ciclo di vita della pagina, nonché gli eventi che segnalano le transizioni tra questi stati, è con un diagramma:

Una rappresentazione visiva del flusso di stati ed eventi descritto in questo documento.
Flusso di eventi e stati dell'API Page Lifecycle.

Stati

La tabella seguente spiega in dettaglio ogni stato. Elenca anche i possibili stati che possono precedere e seguire, nonché gli eventi che gli sviluppatori possono utilizzare per osservare le modifiche.

Stato Descrizione
Attivi

Una pagina è nello stato attivo se è visibile e ha il focus di input.

Stati precedenti possibili:
passive (tramite l'evento focus)
frozen (tramite l'evento resume, poi l'evento pageshow)

Possibili stati successivi:
passive (tramite l'evento blur)

Passivo

Una pagina è in stato passivo se è visibile e non ha il focus di input.

Stati precedenti possibili:
active (tramite l'evento blur)
hidden (tramite l'evento visibilitychange)
frozen (tramite l'evento resume, poi l'evento pageshow)

Possibili stati successivi:
active (tramite l'evento focus)
hidden (tramite l'evento visibilitychange)

Nascosto

Una pagina è nello stato nascosta se non è visibile (e non è stata bloccata, eliminata o terminata).

Possibili stati precedenti:
passive (tramite l'evento visibilitychange)
frozen (tramite l'evento resume, poi l'evento pageshow)

Possibili stati successivi:
passive (tramite l'evento visibilitychange)
frozen (tramite l'evento freeze)
discarded (nessun evento attivato)
terminated (nessun evento attivato)

Congelato

Nello stato congelato, il browser sospende l'esecuzione delle attività congelabili nelle code di attività della pagina fino a quando la pagina non viene scongelata. Ciò significa che elementi come i timer JavaScript e i callback di recupero non vengono eseguiti. Le attività già in esecuzione possono essere completate (soprattutto il callback freeze), ma potrebbero essere limitate in ciò che possono fare e per quanto tempo possono essere eseguite.

I browser bloccano le pagine per preservare l'utilizzo di CPU, batteria e dati; lo fanno anche per consentire una navigazione più rapida avanti/indietro, evitando la necessità di ricaricare completamente la pagina.

Possibili stati precedenti:
hidden (tramite l'evento freeze)

Possibili stati successivi:
active (tramite l'evento resume, poi l'evento pageshow)
passive (tramite l'evento resume, poi l'evento pageshow)
hidden (tramite l'evento resume)
discarded (nessun evento attivato)

Risolto

Una pagina si trova nello stato terminato una volta che il browser ha iniziato a scaricarla e a cancellarla dalla memoria. No nuove attività possono essere avviate in questo stato e le attività in corso potrebbero essere interrotte se vengono eseguite troppo a lungo.

Possibili stati precedenti:
hidden (tramite l'evento pagehide)

Possibili stati successivi:
NESSUNO

Ignorato

Una pagina è nello stato ignorata quando viene scaricata dal browser per risparmiare risorse. In questo stato non possono essere eseguiti attività, callback di eventi o JavaScript di alcun tipo, poiché gli scarti in genere si verificano in presenza di vincoli di risorse, dove l'avvio di nuovi processi è impossibile.

Nello stato Eliminata, la scheda stessa (inclusi il titolo e la favicon) è in genere visibile all'utente anche se la pagina non è più presente.

Possibili stati precedenti:
hidden (nessun evento attivato)
frozen (nessun evento attivato)

Possibili stati successivi:
NESSUNO

Eventi

I browser inviano molti eventi, ma solo una piccola parte di questi segnala un possibile cambiamento nello stato del ciclo di vita della pagina. La tabella seguente descrive tutti gli eventi relativi al ciclo di vita ed elenca gli stati da cui e verso cui possono passare.

Nome Dettagli
focus

Un elemento DOM ha ricevuto lo stato attivo.

Nota:un evento focus non segnala necessariamente una modifica dello stato. Segnala una modifica dello stato solo se la pagina non aveva precedentemente il focus di input.

Stati precedenti possibili:
passive

Stati attuali possibili:
active

blur

Un elemento DOM ha perso lo stato attivo.

Nota:un evento blur non segnala necessariamente una modifica dello stato. Indica una modifica dello stato solo se la pagina non ha più il focus di input (ovvero la pagina non ha appena spostato il focus da un elemento all'altro).

Stati precedenti possibili:
active

Stati attuali possibili:
passive

visibilitychange

Il valore visibilityState del documento è cambiato. Ciò può accadere quando un utente passa a una nuova pagina, cambia scheda, chiude una scheda, riduce a icona o chiude il browser oppure cambia app sui sistemi operativi mobile.

Possibili stati precedenti:
passive
hidden

Possibili stati attuali:
passive
hidden

freeze *

La pagina è stata appena bloccata. Nessuna attività congelabile nelle code di attività della pagina verrà avviata.

Stati precedenti possibili:
hidden

Possibili stati attuali:
frozen

resume *

Il browser ha ripristinato una pagina bloccata.

Stati precedenti possibili:
frozen

Possibili stati attuali:
active (se seguito dall'evento pageshow)
passive (se seguito dall'evento pageshow)
hidden

pageshow

Si sta passando a una voce della cronologia delle sessioni.

Potrebbe trattarsi di un caricamento di una pagina nuova o di una pagina presa dalla cache back-forward. Se la pagina è stata presa dalla cache back-forward, la proprietà persisted dell'evento è true, altrimenti è false.

Possibili stati precedenti:
frozen (sarebbe stato attivato anche un evento resume)

Stati attuali possibili:
active
passive
hidden

pagehide

Una voce della cronologia delle sessioni viene attraversata.

Se l'utente passa a un'altra pagina e il browser è in grado di aggiungere la pagina corrente alla cache indietro/avanti per essere riutilizzata in un secondo momento, la proprietà persisted dell'evento è true. Quando true, la pagina entra nello stato congelato, altrimenti entra nello stato terminato.

Stati precedenti possibili:
hidden

Possibili stati attuali:
frozen (event.persisted è true, freeze event follows)
terminated (event.persisted è false, unload event follows)

beforeunload

La finestra, il documento e le relative risorse stanno per essere scaricati. Il documento è ancora visibile e l'evento è ancora annullabile a questo punto.

Importante:l'evento beforeunload deve essere utilizzato solo per avvisare l'utente delle modifiche non salvate. Una volta salvate le modifiche, l'evento dovrebbe essere rimosso. Non deve mai essere aggiunto in modo incondizionato alla pagina, in quanto ciò può influire negativamente sul rendimento in alcuni casi. Per i dettagli, consulta la sezione API legacy.

Stati precedenti possibili:
hidden

Stati attuali possibili:
terminated

unload

La pagina viene scaricata.

Avviso:l'utilizzo dell'evento unload non è mai consigliato perché non è affidabile e in alcuni casi può influire negativamente sulle prestazioni. Per ulteriori dettagli, consulta la sezione sulle API legacy.

Stati precedenti possibili:
hidden

Stati attuali possibili:
terminated

* Indica un nuovo evento definito dall'API Page Lifecycle

Nuove funzionalità aggiunte in Chrome 68

Il grafico precedente mostra due stati avviati dal sistema anziché dall'utente: frozen e discarded. Come accennato in precedenza, i browser di oggi a volte si bloccano e chiudono le schede nascoste (a loro discrezione), ma gli sviluppatori non hanno modo di sapere quando ciò accade.

In Chrome 68, gli sviluppatori possono ora osservare quando una scheda nascosta viene bloccata e sbloccata ascoltando gli eventi freeze e resume su document.

document.addEventListener('freeze', (event) => {
  // The page is now frozen.
});

document.addEventListener('resume', (event) => {
  // The page has been unfrozen.
});

A partire da Chrome 68, l'oggetto document ora include una proprietà wasDiscarded su Chrome desktop (il supporto di Android è in fase di monitoraggio in questo problema). Per determinare se una pagina è stata eliminata mentre si trovava in una scheda nascosta, puoi esaminare il valore di questa proprietà al momento del caricamento della pagina (nota: le pagine eliminate devono essere ricaricate per essere utilizzate di nuovo).

if (document.wasDiscarded) {
  // Page was previously discarded by the browser while in a hidden tab.
}

Per consigli su cosa è importante fare negli eventi freeze e resume, nonché su come gestire e prepararsi per l'eliminazione delle pagine, consulta i consigli per gli sviluppatori per ogni stato.

Le sezioni successive offrono una panoramica di come queste nuove funzionalità si inseriscono negli stati ed eventi esistenti della piattaforma web.

Come osservare gli stati del ciclo di vita della pagina nel codice

Negli stati attivo, passivo e nascosto, è possibile eseguire codice JavaScript che determina lo stato del ciclo di vita della pagina corrente dalle API della piattaforma web esistenti.

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

Gli stati congelato e terminato, d'altra parte, possono essere rilevati solo nei rispettivi listener di eventi (freeze e pagehide) durante la modifica dello stato.

Come osservare le modifiche dello stato

Basandosi sulla funzione getState() definita in precedenza, puoi osservare tutte le modifiche dello stato del ciclo di vita della pagina con il seguente codice.

// Stores the initial state using the `getState()` function (defined above).
let state = getState();

// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
  const prevState = state;
  if (nextState !== prevState) {
    console.log(`State change: ${prevState} >>> ${nextState}`);
    state = nextState;
  }
};

// Options used for all event listeners.
const opts = {capture: true};

// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
  window.addEventListener(type, () => logStateChange(getState()), opts);
});

// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
  // In the freeze event, the next state is always frozen.
  logStateChange('frozen');
}, opts);

window.addEventListener('pagehide', (event) => {
  // If the event's persisted property is `true` the page is about
  // to enter the back/forward cache, which is also in the frozen state.
  // If the event's persisted property is not `true` the page is
  // about to be unloaded.
  logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);

Questo codice esegue tre operazioni:

  • Imposta lo stato iniziale utilizzando la funzione getState().
  • Definisce una funzione che accetta uno stato successivo e, se si verifica una modifica, registra le modifiche dello stato nella console.
  • Aggiunge l'acquisizione di listener di eventi per tutti gli eventi del ciclo di vita necessari, che a loro volta chiamano logStateChange(), passando allo stato successivo.

Una cosa da notare del codice è che tutti i listener di eventi vengono aggiunti a window e tutti passano {capture: true}. Ecco alcuni dei motivi:

  • Non tutti gli eventi del ciclo di vita della pagina hanno lo stesso target. pagehide e pageshow vengono attivati su window; visibilitychange, freeze e resume vengono attivati su document, mentre focus e blur vengono attivati sui rispettivi elementi DOM.
  • La maggior parte di questi eventi non si propaga, il che significa che è impossibile aggiungere listener di eventi non di acquisizione a un elemento antenato comune e osservarli tutti.
  • La fase di acquisizione viene eseguita prima delle fasi di destinazione o di bolla, quindi l'aggiunta di listener in questa fase contribuisce a garantire che vengano eseguiti prima che altro codice possa annullarli.

Consigli per gli sviluppatori per ogni stato

In qualità di sviluppatori, è importante sia comprendere gli stati del ciclo di vita della pagina sia sapere come osservarli nel codice, perché il tipo di lavoro che devi (e non devi) svolgere dipende in gran parte dallo stato della pagina.

Ad esempio, non ha senso mostrare una notifica temporanea all'utente se la pagina è in stato nascosto. Anche se questo esempio è piuttosto ovvio, ci sono altri consigli meno evidenti che vale la pena elencare.

Stato Consigli per gli sviluppatori
Active

Lo stato attivo è il momento più critico per l'utente e quindi il momento più importante per la tua pagina per essere reattiva all'input dell'utente.

Qualsiasi lavoro non UI che potrebbe bloccare il thread principale deve essere declassato a periodi di inattività o scaricato su un web worker.

Passive

Nello stato passivo, l'utente non interagisce con la pagina, ma può comunque vederla. Ciò significa che gli aggiornamenti e le animazioni dell'interfaccia utente devono comunque essere fluidi, ma la tempistica di questi aggiornamenti è meno critica.

Quando la pagina passa da attiva a passiva, è il momento giusto per rendere persistente lo stato dell'applicazione non salvato.

Hidden

Quando la pagina passa da passiva a nascosta, è possibile che l'utente non interagisca di nuovo con la pagina finché non viene ricaricata.

La transizione allo stato nascosto è spesso anche l'ultimo cambio di stato che gli sviluppatori possono osservare in modo affidabile (ciò vale soprattutto per i dispositivi mobili, in quanto gli utenti possono chiudere le schede o l'app del browser e gli eventi beforeunload, pagehide e unload non vengono attivati in questi casi).

Ciò significa che devi considerare lo stato nascosto come la probabile fine della sessione dell'utente. In altre parole, mantieni lo stato dell'applicazione non salvato e invia i dati di analisi non inviati.

Dovresti anche interrompere gli aggiornamenti dell'interfaccia utente (poiché non verranno visualizzati dall'utente) e qualsiasi attività che un utente non vorrebbe in esecuzione in background.

Frozen

Nello stato congelato, le attività congelabili nelle code di attività vengono sospese finché la pagina non viene scongelata, il che potrebbe non accadere mai (ad es. se la pagina viene eliminata).

Ciò significa che quando la pagina passa da nascosta a congelata, è essenziale interrompere tutti i timer o chiudere tutte le connessioni che, se congelate, potrebbero influire su altre schede aperte nella stessa origine o sulla capacità del browser di inserire la pagina nella cache indietro/avanti.

In particolare, è importante che tu:

Devi anche rendere persistente qualsiasi stato di visualizzazione dinamico (ad es. la posizione di scorrimento in una visualizzazione elenco infinita) in sessionStorage (o IndexedDB tramite commit()) che vuoi ripristinare se la pagina viene eliminata e ricaricata in un secondo momento.

Se la pagina passa dallo stato congelato a nascosto, puoi riaprire le connessioni chiuse o riavviare il polling interrotto quando la pagina è stata inizialmente congelata.

Terminated

In genere, non è necessario intraprendere alcuna azione quando una pagina passa allo stato terminato.

Poiché le pagine scaricate a seguito dell'azione dell'utente passano sempre attraverso lo stato hidden prima di entrare nello stato terminated, lo stato hidden è quello in cui deve essere eseguita la logica di fine sessione (ad es. la persistenza dello stato dell'applicazione e la generazione di report per Analytics).

Inoltre (come indicato nei consigli per lo stato nascosto), è molto importante che gli sviluppatori si rendano conto che la transizione allo stato terminato non può essere rilevata in modo affidabile in molti casi (soprattutto sui dispositivi mobili), quindi gli sviluppatori che dipendono da eventi di terminazione (ad es. beforeunload, pagehide e unload) probabilmente perdono dati.

Discarded

Lo stato eliminato non è osservabile dagli sviluppatori nel momento in cui una pagina viene eliminata. Questo perché le pagine vengono in genere eliminate in base ai limiti delle risorse e riattivarle solo per consentire l'esecuzione dello script in risposta a un evento di eliminazione non è possibile nella maggior parte dei casi.

Di conseguenza, devi prepararti alla possibilità di un annullamento della modifica da nascosta a congelata, quindi puoi reagire al ripristino di una pagina annullata al momento del caricamento della pagina controllando document.wasDiscarded.

Ancora una volta, poiché l'affidabilità e l'ordinamento degli eventi del ciclo di vita non sono implementati in modo coerente in tutti i browser, il modo più semplice per seguire i consigli riportati nella tabella è utilizzare PageLifecycle.js.

API per il ciclo di vita legacy da evitare

I seguenti eventi devono essere evitati, se possibile.

L'evento unload

Molti sviluppatori considerano l'evento unload come un callback garantito e lo utilizzano come indicatore di fine sessione per salvare lo stato e inviare i dati di analisi, ma questa operazione è estremamente inaffidabile, soprattutto sui dispositivi mobili. L'evento unload non viene attivato in molte situazioni di scaricamento tipiche, tra cui la chiusura di una scheda dal selettore di schede su dispositivo mobile o la chiusura dell'app del browser dal selettore di app.

Per questo motivo, è sempre meglio fare affidamento all'evento visibilitychange per determinare quando termina una sessione e considerare lo stato nascosto come l'ultimo momento affidabile per salvare i dati dell'app e dell'utente.

Inoltre, la semplice presenza di un gestore di eventi unload registrato (tramite onunload o addEventListener()) può impedire ai browser di inserire le pagine nella cache back-forward per caricamenti più rapidi avanti e indietro.

In tutti i browser moderni, ti consigliamo di utilizzare sempre l'evento pagehide per rilevare possibili scaricamenti di pagina (ovvero lo stato terminated) anziché l'evento unload. Se devi supportare Internet Explorer 10 e versioni precedenti, devi rilevare l'evento pagehide e utilizzare unload solo se il browser non supporta pagehide:

const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';

window.addEventListener(terminationEvent, (event) => {
  // Note: if the browser is able to cache the page, `event.persisted`
  // is `true`, and the state is frozen rather than terminated.
});

L'evento beforeunload

L'evento beforeunload presenta un problema simile all'evento unload, in quanto storicamente la presenza di un evento beforeunload poteva impedire alle pagine di essere idonee per la cache back-forward. I browser moderni non hanno questa limitazione. Anche se alcuni browser, per precauzione, non attivano l'evento beforeunload quando tentano di inserire una pagina nella cache indietro/avanti, il che significa che l'evento non è affidabile come indicatore di fine sessione. Inoltre, alcuni browser (incluso Chrome) richiedono un'interazione dell'utente sulla pagina prima di consentire l'attivazione dell'evento beforeunload, influenzandone ulteriormente l'affidabilità.

Una differenza tra beforeunload e unload è che esistono usi legittimi di beforeunload. Ad esempio, quando vuoi avvisare l'utente che ha modifiche non salvate che perderà se continua a scaricare la pagina.

Poiché esistono motivi validi per utilizzare beforeunload, ti consigliamo di aggiungere solo listener beforeunload quando un utente ha modifiche non salvate e di rimuoverli immediatamente dopo il salvataggio.

In altre parole, non fare questo (perché aggiunge un listener beforeunload in modo incondizionato):

addEventListener('beforeunload', (event) => {
  // A function that returns `true` if the page has unsaved changes.
  if (pageHasUnsavedChanges()) {
    event.preventDefault();

    // Legacy support for older browsers.
    event.returnValue = true;
  }
});

Invece, fai così (in quanto aggiunge il listener beforeunload solo quando è necessario e lo rimuove quando non lo è):

const beforeUnloadListener = (event) => {
  event.preventDefault();

  // Legacy support for older browsers.
  event.returnValue = true;
};

// A function that adds a `beforeunload` listener if there are unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

// A function that removes the `beforeunload` listener when the page's unsaved
// changes are resolved.
onAllChangesSaved(() => {
  removeEventListener('beforeunload', beforeUnloadListener);
});

Domande frequenti

Perché non è presente uno stato "Caricamento"?

L'API Page Lifecycle definisce stati discreti e reciprocamente esclusivi. Poiché una pagina può essere caricata nello stato attivo, passivo o nascosto e poiché può cambiare stato o addirittura essere terminata prima del completamento del caricamento, uno stato di caricamento separato non ha senso in questo paradigma.

La mia pagina svolge un lavoro importante quando è nascosta. Come posso impedire che venga bloccata o eliminata?

Esistono molti motivi legittimi per cui le pagine web non devono essere bloccate durante l'esecuzione nello stato nascosto. L'esempio più ovvio è un'app che riproduce musica.

Esistono anche situazioni in cui sarebbe rischioso per Chrome eliminare una pagina, ad esempio se contiene un modulo con input utente non inviati o se ha un gestore beforeunload che avvisa quando la pagina viene scaricata.

Per il momento, Chrome sarà conservativo quando scarta le pagine e lo farà solo quando sarà sicuro che non influirà sugli utenti. Ad esempio, le pagine che hanno eseguito una delle seguenti operazioni in stato nascosto non verranno eliminate, a meno che non si verifichino vincoli estremi delle risorse:

  • Riproduzione audio
  • Utilizzo di WebRTC
  • Aggiornamento del titolo della tabella o della favicon
  • Visualizzazione degli avvisi
  • Invio di notifiche push

Per l'elenco attuale delle funzionalità utilizzate per determinare se una scheda può essere bloccata o eliminata in modo sicuro, consulta: Euristiche per il blocco e l'eliminazione in Chrome.

Che cos'è la cache back-forward?

La cache back-forward è un termine utilizzato per descrivere un'ottimizzazione della navigazione implementata da alcuni browser che rende più veloce l'utilizzo dei pulsanti Indietro e Avanti.

Quando un utente esce da una pagina, questi browser bloccano una versione della pagina in modo che possa essere ripresa rapidamente nel caso in cui l'utente torni indietro utilizzando i pulsanti Indietro o Avanti. Ricorda che l'aggiunta di un unload gestore eventi impedisce questa ottimizzazione.

A tutti gli effetti, questo blocco è funzionalmente identico a quello eseguito dai browser per risparmiare CPU/batteria; per questo motivo, è considerato parte dello stato del ciclo di vita congelato.

Se non riesco a eseguire API asincrone negli stati bloccato o terminato, come faccio a salvare i dati in IndexedDB?

Negli stati congelato e terminato, le attività congelabili nelle code di attività di una pagina vengono sospese, il che significa che le API asincrone e basate su callback non possono essere utilizzate in modo affidabile.

Sebbene la maggior parte delle API IndexedDB sia basata su callback, il metodo commit() dell'interfaccia IDBTransaction fornisce un modo per avviare la procedura di commit su una transazione attiva senza attendere l'invio degli eventi dalle richieste in sospeso. In questo modo viene fornito un modo affidabile per salvare i dati in un database IndexedDB in un listener di eventi freeze o visibilitychange perché il commit viene eseguito immediatamente anziché essere messo in coda in un'attività separata.

Testare l'app negli stati congelato e eliminato

Per testare il comportamento dell'app negli stati di blocco e chiusura, puoi visitare chrome://discards per bloccare o chiudere effettivamente una delle tue schede aperte.

Interfaccia utente di Chrome Discards
Interfaccia utente di Chrome Discards

In questo modo, puoi assicurarti che la pagina gestisca correttamente gli eventi freeze e resume nonché il flag document.wasDiscarded quando le pagine vengono ricaricate dopo un'eliminazione.

Riepilogo

Gli sviluppatori che vogliono rispettare le risorse di sistema dei dispositivi dei loro utenti devono creare le loro app tenendo presente gli stati del ciclo di vita della pagina. È fondamentale che le pagine web non consumino risorse di sistema eccessive in situazioni che l'utente non si aspetta.

Più sviluppatori iniziano a implementare le nuove API Page Lifecycle, più sarà sicuro per i browser bloccare e scartare le pagine che non vengono utilizzate. Ciò significa che i browser consumeranno meno memoria, CPU, batteria e risorse di rete, il che è un vantaggio per gli utenti.