API Page Lifecycle

Browser Support

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

Aujourd'hui, les navigateurs récents suspendent parfois les pages ou les suppriment complètement lorsque les ressources système sont limitées. À l'avenir, les navigateurs souhaiteront effectuer cette opération de manière proactive afin de consommer moins d'énergie et de mémoire. L'API Page Lifecycle fournit des hooks de cycle de vie pour que vos pages puissent gérer ces interventions du navigateur de manière sécurisée, sans affecter l'expérience utilisateur. Consultez l'API pour déterminer si vous devez implémenter ces fonctionnalités dans votre application.

Arrière-plan

Le cycle de vie des applications est un moyen clé pour les systèmes d'exploitation modernes de gérer les ressources. Sur Android, iOS et les versions récentes de Windows, les applications peuvent être démarrées et arrêtées à tout moment par l'OS. Cela permet à ces plates-formes de rationaliser et de réaffecter les ressources là où elles sont les plus utiles pour l'utilisateur.

Sur le Web, il n'y a jamais eu de cycle de vie de ce type, et les applications peuvent être maintenues en vie indéfiniment. Lorsqu'un grand nombre de pages Web sont exécutées, les ressources système critiques telles que la mémoire, le processeur, la batterie et le réseau peuvent être sursouscrites, ce qui entraîne une mauvaise expérience utilisateur.

Bien que la plate-forme Web dispose depuis longtemps d'événements liés aux états du cycle de vie (comme load, unload et visibilitychange), ces événements ne permettent aux développeurs que de répondre aux changements d'état du cycle de vie initiés par l'utilisateur. Pour que le Web fonctionne de manière fiable sur les appareils peu puissants (et pour être plus économe en ressources en général sur toutes les plates-formes), les navigateurs ont besoin d'un moyen de récupérer et de réattribuer de manière proactive les ressources système.

En fait, les navigateurs actuels prennent déjà des mesures actives pour économiser les ressources des pages dans les onglets en arrière-plan, et de nombreux navigateurs (en particulier Chrome) aimeraient en faire beaucoup plus pour réduire leur empreinte globale en termes de ressources.

Le problème est que les développeurs n'ont aucun moyen de se préparer à ces types d'interventions initiées par le système ni même de savoir qu'elles se produisent. Cela signifie que les navigateurs doivent être prudents, sous peine de casser les pages Web.

L'API Page Lifecycle tente de résoudre ce problème en :

  • Présentation et standardisation du concept d'états de cycle de vie sur le Web.
  • Définition de nouveaux états initiés par le système qui permettent aux navigateurs de limiter les ressources pouvant être consommées par les onglets masqués ou inactifs.
  • Créer de nouvelles API et de nouveaux événements permettant aux développeurs Web de répondre aux transitions vers et depuis ces nouveaux états initiés par le système.

Cette solution offre aux développeurs Web la prévisibilité dont ils ont besoin pour créer des applications résilientes aux interventions du système. Elle permet également aux navigateurs d'optimiser plus agressivement les ressources système, ce qui profite à tous les utilisateurs Web.

Le reste de cet article présente les nouvelles fonctionnalités du cycle de vie des pages et explique comment elles sont liées à tous les états et événements existants de la plate-forme Web. Il fournira également des recommandations et des bonnes pratiques concernant les types de tâches que les développeurs doivent (et ne doivent pas) effectuer dans chaque état.

Présentation des états et des événements du cycle de vie des pages

Tous les états du cycle de vie d'une page sont distincts et mutuellement exclusifs, ce qui signifie qu'une page ne peut se trouver que dans un seul état à la fois. La plupart des modifications apportées à l'état du cycle de vie d'une page sont généralement observables via des événements DOM (consultez les recommandations pour les développeurs pour chaque état pour connaître les exceptions).

Le diagramme ci-dessous est peut-être le moyen le plus simple d'expliquer les états du cycle de vie d'une page, ainsi que les événements qui signalent les transitions entre eux :

Représentation visuelle du flux d'état et d'événements décrit dans ce document.
Flux d'état et d'événements de l'API Page Lifecycle.

États

Le tableau suivant explique chaque état en détail. Il liste également les états possibles avant et après, ainsi que les événements que les développeurs peuvent utiliser pour observer les changements.

État Description
Actif

Une page est à l'état active si elle est visible et si elle a le focus d'entrée.

États précédents possibles :
passive (via l'événement focus)
frozen (via l'événement resume, puis l'événement pageshow)

États suivants possibles :
passive (via l'événement blur)

Passif

Une page est à l'état passif si elle est visible et ne dispose pas du focus d'entrée.

États précédents possibles :
active (via l'événement blur)
hidden (via l'événement visibilitychange)
frozen (via l'événement resume, puis l'événement pageshow)

États suivants possibles :
active (via l'événement focus)
hidden (via l'événement visibilitychange)

Hidden

Une page est dans l'état masqué si elle n'est pas visible (et n'a pas été figée, supprimée ni arrêtée).

États précédents possibles :
passive (via l'événement visibilitychange)
frozen (via l'événement resume, puis l'événement pageshow)

États suivants possibles :
passive (via l'événement visibilitychange)
frozen (via l'événement freeze)
discarded (aucun événement déclenché)
terminated (aucun événement déclenché)

Gelé

Dans l'état figé, le navigateur suspend l'exécution des tâches dans les files d'attente de tâches de la page jusqu'à ce que la page soit dégelée. Cela signifie que les éléments tels que les minuteurs JavaScript et les rappels de récupération ne s'exécutent pas. Les tâches déjà en cours d'exécution peuvent se terminer (en particulier le rappel freeze), mais elles peuvent être limitées dans ce qu'elles peuvent faire et dans la durée de leur exécution.

Les navigateurs figent les pages pour préserver l'utilisation du processeur, de la batterie et des données. Ils le font également pour permettre des navigations en arrière/en avant plus rapides, en évitant d'avoir à recharger complètement la page.

États précédents possibles :
hidden (via l'événement freeze)

États suivants possibles :
active (via l'événement resume, puis l'événement pageshow)
passive (via l'événement resume, puis l'événement pageshow)
hidden (via l'événement resume)
discarded (aucun événement déclenché)

Résilié

Une page est à l'état terminated (terminé) une fois qu'elle a commencé à être déchargée et effacée de la mémoire par le navigateur. Dans cet état, aucune nouvelle tâche ne peut démarrer, et les tâches en cours peuvent être arrêtées si elles durent trop longtemps.

États précédents possibles :
hidden (via l'événement pagehide)

États suivants possibles :
AUCUN

Supprimé

Une page est à l'état supprimé lorsqu'elle est déchargée par le navigateur afin d'économiser des ressources. Aucune tâche, aucun rappel d'événement ni aucun code JavaScript ne peuvent s'exécuter dans cet état, car les suppressions se produisent généralement en cas de contraintes de ressources, où il est impossible de démarrer de nouveaux processus.

Dans l'état Supprimée, l'onglet lui-même (y compris son titre et sa favicon) est généralement visible par l'utilisateur, même si la page a disparu.

États précédents possibles :
hidden (aucun événement déclenché)
frozen (aucun événement déclenché)

États suivants possibles :
AUCUN

Événements

Les navigateurs envoient de nombreux événements, mais seule une petite partie d'entre eux signale un changement possible dans l'état du cycle de vie de la page. Le tableau suivant décrit tous les événements liés au cycle de vie et indique les états vers lesquels et depuis lesquels ils peuvent passer.

Nom Détails
focus

Un élément DOM a été sélectionné.

Remarque : Un événement focus ne signale pas nécessairement un changement d'état. Il ne signale un changement d'état que si la page n'avait pas précédemment la sélection d'entrée.

États précédents possibles :
passive

États actuels possibles :
active

blur

Un élément DOM a perdu le focus.

Remarque : Un événement blur ne signale pas nécessairement un changement d'état. Il ne signale un changement d'état que si la page n'a plus le focus d'entrée (c'est-à-dire si la page n'a pas simplement transféré le focus d'un élément à un autre).

États précédents possibles :
active

États actuels possibles :
passive

visibilitychange

La valeur visibilityState du document a changé. Cela peut se produire lorsqu'un utilisateur accède à une nouvelle page, change d'onglet, ferme un onglet, réduit ou ferme le navigateur, ou change d'application sur les systèmes d'exploitation mobiles.

États précédents possibles :
passive
hidden

États actuels possibles :
passive
hidden

freeze *

La page vient d'être figée. Aucune tâche susceptible d'être figée dans les files d'attente des tâches de la page ne sera démarrée.

États précédents possibles :
hidden

États actuels possibles :
frozen

resume *

Le navigateur a repris une page figée.

États précédents possibles :
frozen

États actuels possibles :
active (si suivi de l'événement pageshow)
passive (si suivi de l'événement pageshow)
hidden

pageshow

Une entrée de l'historique de session est en cours de parcours.

Il peut s'agir d'un tout nouveau chargement de page ou d'une page extraite du cache amélioré. Si la page a été extraite du cache amélioré, la propriété persisted de l'événement est définie sur true. Sinon, elle est définie sur false.

États précédents possibles :
frozen (un événement resume aurait également été déclenché)

États actuels possibles :
active
passive
hidden

pagehide

Une entrée de l'historique des sessions est en cours de parcours.

Si l'utilisateur accède à une autre page et que le navigateur peut ajouter la page actuelle au cache Précédent/Suivant pour la réutiliser ultérieurement, la propriété persisted de l'événement est définie sur true. Lorsque true, la page passe à l'état frozen. Sinon, elle passe à l'état terminated.

États précédents possibles :
hidden

États actuels possibles :
frozen (event.persisted est défini sur "true", l'événement freeze suit)
terminated (event.persisted est défini sur "false", l'événement unload suit)

beforeunload

La fenêtre, le document et ses ressources sont sur le point d'être déchargés. À ce stade, le document est toujours visible et l'événement peut toujours être annulé.

Important : L'événement beforeunload ne doit être utilisé que pour avertir l'utilisateur des modifications non enregistrées. Une fois ces modifications enregistrées, l'événement devrait être supprimé. Il ne doit jamais être ajouté de manière inconditionnelle à la page, car cela peut nuire aux performances dans certains cas. Pour en savoir plus, consultez la section Anciennes API.

États précédents possibles :
hidden

États actuels possibles :
terminated

unload

La page est en cours de déchargement.

Avertissement : L'utilisation de l'événement unload n'est jamais recommandée, car il n'est pas fiable et peut nuire aux performances dans certains cas. Pour en savoir plus, consultez la section Anciennes API.

États précédents possibles :
hidden

États actuels possibles :
terminated

* Indique un nouvel événement défini par l'API Page Lifecycle

Nouvelles fonctionnalités ajoutées dans Chrome 68

Le graphique précédent montre deux états initiés par le système plutôt que par l'utilisateur : gelé et supprimé. Comme indiqué précédemment, les navigateurs actuels gèlent et suppriment déjà parfois les onglets masqués (à leur discrétion), mais les développeurs n'ont aucun moyen de savoir quand cela se produit.

Dans Chrome 68, les développeurs peuvent désormais observer quand un onglet masqué est figé et défigé en écoutant les événements freeze et resume sur document.

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

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

À partir de Chrome 68, l'objet document inclut désormais une propriété wasDiscarded sur Chrome pour ordinateur (la compatibilité avec Android est en cours de suivi dans ce problème). Pour déterminer si une page a été supprimée alors qu'elle se trouvait dans un onglet masqué, vous pouvez inspecter la valeur de cette propriété au moment du chargement de la page (notez que les pages supprimées doivent être rechargées pour être réutilisées).

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

Pour obtenir des conseils sur les actions importantes à effectuer dans les événements freeze et resume, ainsi que sur la manière de gérer et de préparer la suppression des pages, consultez les recommandations pour les développeurs pour chaque état.

Les sections suivantes présentent un aperçu de la façon dont ces nouvelles fonctionnalités s'intègrent aux états et événements existants de la plate-forme Web.

Observer les états du cycle de vie des pages dans le code

Dans les états actif, passif et masqué, il est possible d'exécuter du code JavaScript qui détermine l'état actuel du cycle de vie de la page à partir des API de plate-forme Web existantes.

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

En revanche, les états frozen et terminated ne peuvent être détectés que dans leur écouteur d'événements respectif (freeze et pagehide) lorsque l'état change.

Observer les changements d'état

En vous appuyant sur la fonction getState() définie précédemment, vous pouvez observer toutes les modifications de l'état du cycle de vie de la page avec le code suivant.

// 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);

Ce code effectue trois opérations :

  • Définit l'état initial à l'aide de la fonction getState().
  • Définit une fonction qui accepte un état suivant et, en cas de changement, enregistre les changements d'état dans la console.
  • Ajoute des écouteurs d'événements de capture pour tous les événements de cycle de vie nécessaires, qui appellent à leur tour logStateChange() en transmettant l'état suivant.

Il est important de noter que tous les écouteurs d'événements sont ajoutés à window et qu'ils transmettent tous {capture: true}. Plusieurs raisons peuvent expliquer ce phénomène :

  • Tous les événements de cycle de vie de page n'ont pas la même cible. pagehide et pageshow sont déclenchés sur window, visibilitychange, freeze et resume sont déclenchés sur document, et focus et blur sont déclenchés sur leurs éléments DOM respectifs.
  • La plupart de ces événements ne se propagent pas, ce qui signifie qu'il est impossible d'ajouter des écouteurs d'événements sans capture à un élément ancêtre commun et de les observer tous.
  • La phase de capture s'exécute avant les phases cible ou de propagation. L'ajout d'écouteurs à ce niveau permet de s'assurer qu'ils s'exécutent avant que d'autres codes puissent les annuler.

Recommandations pour les développeurs pour chaque état

En tant que développeur, il est important de comprendre les états du cycle de vie des pages et de savoir comment les observer dans le code, car le type de travail que vous devez (et ne devez pas) effectuer dépend en grande partie de l'état de votre page.

Par exemple, il n'est pas logique d'afficher une notification éphémère à l'utilisateur si la page est masquée. Cet exemple est assez évident, mais il existe d'autres recommandations moins évidentes qu'il est utile de mentionner.

État Recommandations pour les développeurs
Active

L'état actif est le plus critique pour l'utilisateur et donc le plus important pour que votre page soit réactive aux entrées utilisateur.

Toute tâche non liée à l'UI qui peut bloquer le thread principal doit être reléguée au second plan pendant les périodes d'inactivité ou déchargée sur un nœud de calcul Web.

Passive

Dans l'état passif, l'utilisateur n'interagit pas avec la page, mais il peut toujours la voir. Cela signifie que les mises à jour et les animations de l'UI doivent toujours être fluides, mais le moment où ces mises à jour se produisent est moins critique.

Lorsque la page passe de l'état active à l'état passive, c'est le bon moment pour rendre persistant l'état de l'application non enregistré.

Hidden

Lorsque la page passe de l'état passif à l'état masqué, il est possible que l'utilisateur n'interagisse plus avec elle tant qu'elle n'est pas rechargée.

La transition vers l'état hidden est souvent la dernière modification d'état que les développeurs peuvent observer de manière fiable (c'est particulièrement vrai sur mobile, car les utilisateurs peuvent fermer des onglets ou l'application de navigateur elle-même, et les événements beforeunload, pagehide et unload ne sont pas déclenchés dans ces cas).

Cela signifie que vous devez considérer l'état hidden comme la fin probable de la session de l'utilisateur. En d'autres termes, conservez tout état d'application non enregistré et envoyez toutes les données analytiques non envoyées.

Vous devez également cesser de mettre à jour l'UI (car l'utilisateur ne les verra pas) et arrêter toutes les tâches qu'un utilisateur ne souhaiterait pas voir s'exécuter en arrière-plan.

Frozen

À l'état figé, les tâches pouvant être figées dans les files d'attente des tâches sont suspendues jusqu'à ce que la page soit dégelée, ce qui peut ne jamais se produire (par exemple, si la page est supprimée).

Cela signifie que lorsque la page passe de l'état masqué à l'état figé, il est essentiel d'arrêter tous les minuteurs ou de fermer toutes les connexions qui, si elles sont figées, pourraient affecter d'autres onglets ouverts dans la même origine, ou la capacité du navigateur à placer la page dans le cache Précédent/Suivant.

En particulier, il est important que vous :

Vous devez également conserver tout état de vue dynamique (par exemple, la position de défilement dans une vue de liste infinie) dans sessionStorage (ou IndexedDB via commit()) que vous souhaitez restaurer si la page est supprimée et rechargée ultérieurement.

Si la page passe de l'état gelé à l'état masqué, vous pouvez rouvrir les connexions fermées ou redémarrer l'interrogation que vous avez arrêtée lorsque la page était initialement gelée.

Terminated

En général, aucune action n'est requise de votre part lorsqu'une page passe à l'état terminated (terminé).

Étant donné que les pages déchargées à la suite d'une action de l'utilisateur passent toujours par l'état hidden avant d'entrer dans l'état terminated, c'est dans l'état hidden que la logique de fin de session (par exemple, la persistance de l'état de l'application et le reporting aux outils d'analyse) doit être effectuée.

De plus (comme indiqué dans les recommandations pour l'état hidden), il est très important que les développeurs comprennent que la transition vers l'état terminated ne peut pas être détectée de manière fiable dans de nombreux cas (en particulier sur mobile). Par conséquent, les développeurs qui dépendent des événements de fin (par exemple, beforeunload, pagehide et unload) perdent probablement des données.

Discarded

L'état discarded (supprimé) n'est pas observable par les développeurs au moment où une page est supprimée. En effet, les pages sont généralement supprimées en raison de contraintes de ressources. Il n'est tout simplement pas possible, dans la plupart des cas, de réactiver une page uniquement pour permettre à un script de s'exécuter en réponse à un événement de suppression.

Par conséquent, vous devez vous préparer à la possibilité d'une suppression lors du passage de hidden à frozen. Vous pouvez ensuite réagir à la restauration d'une page supprimée au moment du chargement de la page en vérifiant document.wasDiscarded.

Une fois de plus, étant donné que la fiabilité et l'ordre des événements de cycle de vie ne sont pas implémentés de manière cohérente dans tous les navigateurs, le moyen le plus simple de suivre les conseils du tableau est d'utiliser PageLifecycle.js.

Anciennes API de cycle de vie à éviter

Les événements suivants doivent être évités dans la mesure du possible.

Événement de déchargement

De nombreux développeurs traitent l'événement unload comme un rappel garanti et l'utilisent comme signal de fin de session pour enregistrer l'état et envoyer des données analytiques. Toutefois, cette méthode est extrêmement peu fiable, en particulier sur mobile. L'événement unload ne se déclenche pas dans de nombreuses situations de déchargement typiques, y compris lorsque l'utilisateur ferme un onglet à partir du sélecteur d'onglets sur mobile ou lorsqu'il ferme l'application de navigateur à partir du sélecteur d'applications.

Pour cette raison, il est toujours préférable de s'appuyer sur l'événement visibilitychange pour déterminer quand une session se termine, et de considérer l'état masqué comme la dernière heure fiable pour enregistrer les données de l'application et de l'utilisateur.

De plus, la simple présence d'un gestionnaire d'événements unload enregistré (via onunload ou addEventListener()) peut empêcher les navigateurs de placer des pages dans le cache amélioré pour accélérer les chargements des pages précédentes et suivantes.

Dans tous les navigateurs modernes, il est recommandé d'utiliser systématiquement l'événement pagehide pour détecter les éventuels déchargements de page (c'est-à-dire l'état terminated) plutôt que l'événement unload. Si vous devez prendre en charge les versions 10 et antérieures d'Internet Explorer, vous devez détecter l'événement pagehide et n'utiliser unload que si le navigateur n'est pas compatible avec 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'événement beforeunload

L'événement beforeunload présente un problème similaire à l'événement unload, car historiquement, la présence d'un événement beforeunload pouvait empêcher les pages d'être éligibles au cache amélioré. Cette restriction ne s'applique pas aux navigateurs récents. Par précaution, certains navigateurs ne déclenchent pas l'événement beforeunload lorsqu'ils tentent de placer une page dans le cache Précédent/Suivant. L'événement n'est donc pas fiable comme signal de fin de session. De plus, certains navigateurs (y compris Chrome) exigent une interaction de l'utilisateur sur la page avant d'autoriser le déclenchement de l'événement beforeunload, ce qui affecte encore davantage sa fiabilité.

L'une des différences entre beforeunload et unload est qu'il existe des utilisations légitimes de beforeunload. Par exemple, lorsque vous souhaitez avertir l'utilisateur qu'il a des modifications non enregistrées qu'il perdra s'il continue à décharger la page.

Comme il existe des raisons valables d'utiliser beforeunload, nous vous recommandons de n'ajouter des écouteurs beforeunload que lorsqu'un utilisateur a des modifications non enregistrées, puis de les supprimer immédiatement après leur enregistrement.

En d'autres termes, ne faites pas ceci (car cela ajoute un écouteur beforeunload de manière inconditionnelle) :

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;
  }
});

À la place, procédez comme suit (car cela n'ajoute l'écouteur beforeunload que lorsqu'il est nécessaire et le supprime lorsqu'il ne l'est pas) :

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);
});

Questions fréquentes

Pourquoi n'y a-t-il pas d'état de chargement ?

L'API Page Lifecycle définit des états discrets et mutuellement exclusifs. Étant donné qu'une page peut être chargée à l'état actif, passif ou masqué, et qu'elle peut changer d'état, voire être arrêtée, avant la fin du chargement, un état de chargement distinct n'a pas de sens dans ce paradigme.

Ma page effectue des tâches importantes lorsqu'elle est masquée. Comment puis-je l'empêcher d'être figée ou supprimée ?

Il existe de nombreuses raisons légitimes pour lesquelles les pages Web ne doivent pas être figées lorsqu'elles s'exécutent en état masqué. L'exemple le plus évident est une application qui lit de la musique.

Il existe également des situations où il serait risqué pour Chrome de supprimer une page, par exemple si elle contient un formulaire avec des données utilisateur non envoyées ou si elle comporte un gestionnaire beforeunload qui avertit lorsque la page est en cours de déchargement.

Pour le moment, Chrome va être prudent lorsqu'il supprimera des pages et ne le fera que lorsqu'il sera certain que cela n'affectera pas les utilisateurs. Par exemple, les pages qui ont été observées en train d'effectuer l'une des actions suivantes à l'état masqué ne seront pas supprimées, sauf en cas de contraintes extrêmes en termes de ressources :

  • Lecture d'un contenu audio
  • Utiliser WebRTC
  • Modifier le titre ou la favicon d'un tableau
  • Afficher les alertes
  • Envoyer des notifications push

Pour obtenir la liste actuelle des fonctionnalités utilisées pour déterminer si un onglet peut être mis en veille ou supprimé sans risque, consultez Heuristics for Freezing & Discarding dans Chrome.

Qu'est-ce que le cache amélioré ?

Le cache amélioré est un terme utilisé pour décrire une optimisation de la navigation que certains navigateurs implémentent pour accélérer l'utilisation des boutons "Précédent" et "Suivant".

Lorsqu'un utilisateur quitte une page, ces navigateurs figent une version de cette page afin qu'elle puisse être rapidement reprise au cas où l'utilisateur y reviendrait à l'aide des boutons "Précédent" ou "Suivant". N'oubliez pas que l'ajout d'un gestionnaire d'événements unload empêche cette optimisation.

D'un point de vue fonctionnel, cette mise en veille est identique à celle effectuée par les navigateurs pour économiser le processeur et la batterie. C'est pourquoi elle est considérée comme faisant partie de l'état du cycle de vie mis en veille.

Si je ne peux pas exécuter d'API asynchrones dans les états "gelé" ou "arrêté", comment puis-je enregistrer des données dans IndexedDB ?

Dans les états figé et arrêté, les tâches pouvant être figées dans les files d'attente des tâches d'une page sont suspendues, ce qui signifie que les API asynchrones et basées sur des rappels ne peuvent pas être utilisées de manière fiable.

Alors que la plupart des API IndexedDB sont basées sur des rappels, la méthode commit() sur l'interface IDBTransaction permet de lancer le processus de validation sur une transaction active sans attendre que les événements des requêtes en attente soient distribués. Cela permet d'enregistrer de manière fiable des données dans une base de données IndexedDB dans un écouteur d'événements freeze ou visibilitychange, car la validation est exécutée immédiatement plutôt que d'être mise en file d'attente dans une tâche distincte.

Tester votre application dans les états "gelé" et "supprimé"

Pour tester le comportement de votre application dans les états "gelé" et "supprimé", vous pouvez accéder à chrome://discards pour geler ou supprimer l'un de vos onglets ouverts.

UI de suppression de Chrome
UI de suppression Chrome

Cela vous permet de vous assurer que votre page gère correctement les événements freeze et resume, ainsi que l'indicateur document.wasDiscarded lorsque les pages sont rechargées après une suppression.

Résumé

Les développeurs qui souhaitent respecter les ressources système des appareils de leurs utilisateurs doivent concevoir leurs applications en tenant compte des états du cycle de vie des pages. Il est essentiel que les pages Web ne consomment pas de ressources système excessives dans des situations auxquelles l'utilisateur ne s'attend pas.

Plus les développeurs commenceront à implémenter les nouvelles API Page Lifecycle, plus les navigateurs pourront geler et supprimer les pages inutilisées en toute sécurité. Cela signifie que les navigateurs consommeront moins de mémoire, de processeur, de batterie et de ressources réseau, ce qui est un avantage pour les utilisateurs.