API Page Lifecycle

Supporto dei browser

  • Chrome: 68.
  • Edge: 79.
  • Firefox: non supportato.
  • Safari: non supportato.

I browser moderni a volte sospendono le pagine o le ignorano del tutto quando le risorse di sistema sono limitate. In futuro, i browser vorranno eseguire questa operazione in modo proattivo, in modo da consumare meno energia e memoria. L'API Page Lifecycle fornisce hook di ciclo di vita in modo che le tue 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 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 riallocare le risorse nel punto in cui offrono maggiori vantaggi all'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, con conseguente esperienza utente 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 bassa potenza (e sia più attento alle risorse in generale su tutte le piattaforme), i browser devono avere un modo per recuperare e riallocare in modo proattivo le risorse di sistema.

Infatti, oggi i browser 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 di sapere nemmeno che si stanno verificando. Ciò significa che i browser devono essere prudenti per non rischiare di danneggiare le pagine web.

L'API Page Lifecycle cerca di risolvere questo problema nel modo seguente:

  • 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 dalle schede nascoste o non attive.
  • Creazione di nuove API ed eventi che consentano agli sviluppatori web di rispondere alle transizioni verso e da questi nuovi stati avviati dal sistema.

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

Nel resto di questo post verranno presentate le nuove funzionalità del ciclo di vita della pagina e verrà spiegato il loro rapporto con tutti gli stati e gli eventi esistenti della piattaforma web. Fornirà inoltre consigli e best practice per i tipi di lavoro che gli sviluppatori dovrebbero (e non dovrebbero) 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 mutuamente esclusivi, il che significa che una pagina può essere in un solo stato alla volta. Inoltre, la maggior parte delle modifiche allo stato del ciclo di vita di una pagina è generalmente osservabile tramite gli eventi DOM (consulta i consigli per gli sviluppatori per ogni stato per le eccezioni).

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

Una rappresentazione visiva dello stato e del flusso di eventi descritti in questo documento.
Flusso di stato ed eventi dell'API Page Lifecycle.

Stati

La tabella seguente illustra in dettaglio ogni stato. Vengono elencati anche i possibili stati che possono precedere e seguire l'evento, nonché gli eventi che gli sviluppatori possono utilizzare per osservare le modifiche.

Stato Descrizione
Attivi

Una pagina è in stato attivo se è visibile e ha lo stato attivo dell'input.

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

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

Passiva

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

Possibili stati precedenti:
attivo (tramite l'evento blur)
nascosto (tramite l'evento visibilitychange)
congelato (tramite l'evento resume, poi l'evento pageshow)

Possibili stati successivi:
attivo (tramite l'evento focus)
nascosto (tramite l'evento visibilitychange)

Nascosto

Una pagina è in stato nascosto se non è visibile (e non è stata bloccata, eliminata o interrotta).

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à bloccabili nelle code di attività della pagina fino a quando la pagina non viene scongelata. Ciò significa che elementi come i timer e i callback di recupero di JavaScript non vengono eseguiti. Le attività già in esecuzione possono essere completate (in particolare il callback freeze), ma potrebbero essere limitate nelle operazioni che possono svolgere e nel tempo di esecuzione.

I browser bloccano le pagine per preservare l'utilizzo di CPU/batteria/dati. Lo fanno anche per consentire navigate avanti/indietro più rapide, evitando la necessità di ricaricare completamente la pagina.

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

Possibili stati successivi:
attivo (tramite l'evento resume, poi l'evento pageshow)
passivo (tramite l'evento resume, poi l'evento pageshow)

}12}evento nascosto
(senza eventi nascosti) pageshow

12}(evento nascosto)

12}resume

Risoluzione

Una pagina è nello stato terminata quando inizia a essere scaricata e cancellata dalla memoria dal browser. In questo stato non è possibile avviare nuove attività e quelle in corso potrebbero essere interrotte se vengono eseguite per troppo tempo.

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

Possibili stati successivi:
NESSUNO

Ignorati

Una pagina è in stato eliminata quando viene scaricata dal browser per risparmiare risorse. In questo stato non è possibile eseguire attività, callback di eventi o JavaScript di alcun tipo, poiché gli scarti si verificano in genere in caso di vincoli di risorse, in cui è impossibile avviare nuovi processi.

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

Possibili stati precedenti:
hidden (no events fired)
frozen (no events fired)

Possibili stati successivi:
NESSUNO

Eventi

I browser inviano molti eventi, ma solo una piccola parte di questi segnala una possibile variazione dello stato del ciclo di vita della pagina. La tabella seguente illustra tutti gli eventi correlati al ciclo di vita ed elenca gli stati a cui possono passare e da cui possono passare.

Nome Dettagli
focus

Un elemento DOM ha ricevuto lo stato attivo.

Nota: un evento focus non segnala necessariamente un cambiamento di stato. Indica una modifica di stato solo se la pagina non aveva precedentemente il focus sull'input.

Possibili stati precedenti:
passivo

Possibili stati attuali:
active

blur

Un elemento DOM ha perso il focus.

Nota: un evento blur non indica necessariamente una variazione di stato. Indica una modifica di stato solo se la pagina non ha più il focus sull'input (ovvero se la pagina non ha semplicemente trasferito il focus da un elemento all'altro).

Possibili stati precedenti:
attivo

Possibili stati attuali:
passive

visibilitychange

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

Possibili stati precedenti:
passive
hidden

Possibili stati attuali:
passivo
nascosto

freeze *

La pagina è stata appena bloccata. Le attività congelabili nelle code di attività della pagina non verranno avviate.

Possibili stati precedenti:
hidden

Possibili stati correnti:
frozen

resume *

Il browser ha ripreso una pagina congelata.

Possibili stati precedenti:
frozen

Possibili stati correnti:
attivo (se seguito dall'evento pageshow)
passivo (se seguito dall'evento pageshow)
nascosto

pageshow

È in corso il raggiungimento di una voce della cronologia delle sessioni.

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

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

Possibili stati attuali:
attivo
passivo
nascosto

pagehide

È in corso l'accesso a una cronologia delle sessioni.

Se l'utente passa a un'altra pagina e il browser è in grado di aggiungere la pagina corrente alla cache di navigazione вперед/назад per riutilizzarla in un secondo momento, la proprietà persisted dell'evento è true. Quando true, la pagina sta entrando nello stato congelato, altrimenti entra nello stato terminato.

Possibili stati precedenti:
hidden

Possibili stati correnti:
congelato (event.persisted è vero, segue l'evento freeze)
terminato (event.persisted è falso, segue l'evento unload)

beforeunload

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

Importante: l'evento beforeunload deve essere utilizzato solo per avvisare l'utente delle modifiche non salvate. Una volta salvate queste modifiche, l'evento dovrebbe essere rimosso. Non deve mai essere aggiunto incondizionatamente alla pagina, in quanto in alcuni casi può compromettere il rendimento. Per maggiori dettagli, consulta la sezione relativa alle API legacy.

Possibili stati precedenti:
hidden

Possibili stati attuali:
terminated

unload

È in corso l'unload della pagina.

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

Possibili stati precedenti:
hidden

Possibili stati attuali:
terminata

* 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: congelato e eliminato. Come accennato in precedenza, oggi i browser bloccano e ignorano occasionalmente le schede nascoste (a loro discrezione), ma gli sviluppatori non hanno modo di sapere quando accade.

In Chrome 68, ora gli sviluppatori possono 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 per computer desktop (L'assistenza Android è monitorata in questo problema). Per determinare se una pagina è stata ignorata in una scheda nascosta, puoi controllare il valore di questa proprietà al momento del caricamento della pagina (nota: le pagine ignorate devono essere ricaricate per essere riutilizzate).

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 all'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 e negli eventi della piattaforma web esistenti.

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

Negli stati active, passive e hidden, è possibile eseguire codice JavaScript che determina lo stato corrente del ciclo di vita della pagina 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, invece, possono essere rilevati solo nel rispettivo listener di eventi (freeze e pagehide) quando lo stato sta cambiando.

Come osservare i cambiamenti di stato

Basandoti 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, in caso di modifica, registra le modifiche dello stato nella console.
  • Aggiunge ascoltatori di eventi di acquisizione per tutti gli eventi del ciclo di vita necessari, che a loro volta chiamano logStateChange(), passando lo stato successivo.

Una cosa da notare sul codice è che tutti i listener di eventi vengono aggiunti a window e passano tutti {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 e focus e blur vengono attivati sui rispettivi elementi DOM.
  • La maggior parte di questi eventi non mostra le bolle, il che significa che è impossibile aggiungere listener di eventi non acquisisce a un elemento predecessore comune e osservarli tutti.
  • La fase di acquisizione viene eseguita prima delle fasi target o bubble, quindi l'aggiunta di ascoltatori consente di assicurarsi che vengano eseguiti prima che altro codice possa annullarli.

Consigli per gli sviluppatori per ogni stato

In qualità di sviluppatori, è importante comprendere gli stati del ciclo di vita delle pagine e 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 transitoria all'utente se la pagina è nello stato nascosto. Anche se questo esempio è abbastanza chiaro, esistono 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, di conseguenza, il momento più importante per consentire alla tua pagina di essere reattiva all'input degli utenti.

Qualsiasi attività non relativa all'interfaccia utente che potrebbe bloccare il thread principale deve essere riassegnata ai periodi di inattività o caricata su un web worker.

Passive

Nello stato passive l'utente non interagisce con la pagina, ma può comunque visualizzarla. Ciò significa che le animazioni e gli aggiornamenti della UI dovrebbero essere comunque fluidi, ma il momento in cui vengono eseguiti è meno fondamentale.

Quando la pagina passa da attiva a passiva, è un buon momento per mantenere lo stato dell'applicazione non salvato.

Hidden

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

La transizione a hidden è spesso anche l'ultimo cambiamento di stato osservabile in modo affidabile dagli sviluppatori (questo è particolarmente vero sui dispositivi mobili, in quanto gli utenti possono chiudere le schede o l'app browser stessa e gli eventi beforeunload, pagehide e unload non vengono attivati in questi casi).

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

Inoltre, dovresti interrompere gli aggiornamenti dell'interfaccia utente (poiché non verranno visualizzati dall'utente) e tutte le attività che un utente non vorrebbe eseguire in background.

Frozen

Nello stato congelato, le attività bloccabili 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 eventuali timer o eliminare eventuali connessioni che, se congelate, potrebbero influire su altre schede aperte nella stessa origine o sulla capacità del browser di inserire la pagina nella cache di spostamento avanti/indietro.

In particolare, è importante che tu:

Devi anche mantenere invariato 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 da congelata a nascosta, puoi riaprire le connessioni chiuse o riavviare eventuali polling che hai interrotto quando la pagina è stata inizialmente bloccata.

Terminated

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

Poiché le pagine che vengono scaricate a seguito di un'azione dell'utente passano sempre allo stato hidden prima di entrare nello stato terminata, lo stato hidden è quello in cui deve essere eseguita la logica di fine sessione (ad esempio, lo stato dell'applicazione persistente e la generazione di report ad Analytics).

Inoltre, come indicato nei consigli per lo stato hidden, è molto importante che gli sviluppatori comprendano che la transizione allo stato terminated non può essere rilevata in modo affidabile in molti casi (in particolare sui dispositivi mobili), pertanto gli sviluppatori che si basano sugli eventi di interruzione (ad es. beforeunload,pagehide e unload) potrebbero perdere dati.

Discarded

Lo stato eliminata non è osservabile dagli sviluppatori al momento dell'eliminazione di una pagina. Questo perché le pagine vengono in genere eliminate in caso di limitazioni delle risorse e sbloccare una pagina solo per consentire l'esecuzione dello script in risposta a un evento di eliminazione non è semplicemente possibile nella maggior parte dei casi.

Di conseguenza, devi prepararti alla possibilità di un'eliminazione nel passaggio da nascosto a congelato e poi puoi reagire al ripristino di una pagina eliminata al momento del caricamento della pagina controllando document.wasDiscarded.

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

API di ciclo di vita legacy da evitare

Se possibile, evita i seguenti eventi.

Evento unload

Molti sviluppatori trattano l'evento unload come un callback garantito e lo utilizzano come un indicatore di fine sessione per salvare lo stato e inviare i dati di analisi, ma questo approccio è estremamente inaffidabile, soprattutto sui dispositivi mobili. L'evento unload non viene attivato in molte situazioni di svuotamento tipiche, ad esempio la chiusura di una scheda dal selettore di schede sui dispositivi mobili o la chiusura dell'app del browser dal selettore di app.

Per questo motivo, è sempre meglio fare affidamento sull'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 sola 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 avanti e indietro più rapidi.

In tutti i browser moderni, ti consigliamo di utilizzare sempre l'evento pagehide per rilevare possibili unload delle pagine (ovvero lo stato terminato) anziché l'evento unload. Se devi supportare Internet Explorer 10 e versioni precedenti, la funzionalità deve 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 a quello dell'evento unload, in quanto, in passato, 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. Tuttavia, alcuni browser, per precauzione, non attivano l'evento beforeunload quando tentano di inserire una pagina nella cache di spostamento вперед/назад, il che significa che l'evento non è affidabile come indicatore di fine sessione. Inoltre, alcuni browser (tra cui Chrome) richiedono un'interazione dell'utente sulla pagina prima di consentire l'attivazione dell'evento beforeunload, il che influisce ulteriormente sulla sua affidabilità.

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

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

In altre parole, non fare così (poiché aggiunge un ascoltatore beforeunload incondizionatamente):

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

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

Esegui invece questa operazione (poiché aggiunge l'ascoltatore beforeunload solo quando è necessario e lo rimuove quando non è necessario):

const beforeUnloadListener = (event) => {
  event.preventDefault();
  
  // Legacy support for older browsers.
  return (event.returnValue = true);
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

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

Domande frequenti

Perché non esiste uno stato "In caricamento"?

L'API Page Lifecycle definisce gli stati in modo che siano distinti e si escludano a vicenda. Poiché una pagina può essere caricata nello stato attivo, passivo o nascosto e poiché può cambiare stato o addirittura essere interrotta prima del termine del caricamento, uno stato di caricamento distinto non ha senso in questo paradigma.

La mia pagina svolge una funzione importante quando è nascosta. Come posso evitare che venga bloccata o eliminata?

Esistono molti motivi legittimi per cui le pagine web non devono essere bloccate durante l'esecuzione in 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à prudente quando eliminerà le pagine e lo farà solo quando avrà la certezza che non influirà sugli utenti. Ad esempio, le pagine per le quali è stato osservato che eseguono una delle seguenti operazioni nello stato nascosto non verranno eliminate, a meno che non si verifichino vincoli di risorse estremi:

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

Per le funzionalità dell'elenco corrente utilizzate per determinare se una scheda può essere messa in pausa o eliminata in sicurezza, consulta Euristiche per la messa in pausa ed 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 consente di utilizzare più velocemente i 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 gestore di eventi unload impedisce che sia possibile questa ottimizzazione.

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

Se non riesco a eseguire API asincrone negli stati di blocco o terminazione, come faccio a salvare i dati in IndexedDB?

Negli stati di blocco e terminazione, le attività bloccabili nelle code di attesa delle attività di una pagina sono sospese, il che significa che le API asincrone e basate su callback come IndexedDB non possono essere utilizzate in modo affidabile.

In futuro, aggiungeremo un metodo commit() agli oggetti IDBTransaction, che offrirà agli sviluppatori un modo per eseguire transazioni di sola scrittura che non richiedono callback. In altre parole, se lo sviluppatore sta solo scrivendo dati su IndexedDB e non sta eseguendo una transazione complessa costituita da letture e scritture, il metodo commit() sarà in grado di terminare prima della sospensione delle code di attività (supponendo che il database IndexedDB sia già aperto).

Tuttavia, per il codice che deve funzionare oggi, gli sviluppatori hanno due opzioni:

  • Utilizza spazio di archiviazione di sessione: l'archiviazione di sessione è sincrona e viene persistente in tutti gli annullamenti delle pagine.
  • Utilizza IndexedDB dal tuo worker di servizio: un worker di servizio può memorizzare i dati in IndexedDB dopo la chiusura o l'eliminazione della pagina. Nell'ascoltatore di eventi freeze o pagehide puoi inviare dati al tuo service worker tramite postMessage(), e il service worker può gestire il salvataggio dei dati.

Test dell'app in stato bloccato e ignorato

Per testare il comportamento dell'app nello stato bloccato e ignorato, puoi visitare chrome://discards per bloccare o ignorare effettivamente le schede aperte.

Interfaccia utente di Chrome Discards
Chrome elimina l'UI

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 abbandono.

Riepilogo

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

Più sviluppatori iniziano a implementare le nuove API di ciclo di vita delle pagine, più sarà sicuro per i browser bloccare e ignorare le pagine non in uso. Ciò significa che i browser consumeranno meno memoria, CPU, batteria e risorse di rete, il che è un vantaggio per gli utenti.