API Page Lifecycle

Navigateurs pris en charge

  • 68
  • 79
  • x
  • x

Aujourd'hui, les navigateurs récents suspendent parfois des pages ou les suppriment complètement lorsque les ressources système sont limitées. À l'avenir, les navigateurs souhaiteront le faire 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 afin que vos pages puissent gérer ces interventions du navigateur en toute sécurité sans affecter l'expérience utilisateur. Examinez l'API pour déterminer si vous devez mettre en œuvre ces fonctionnalités dans votre application.

Contexte

Le cycle de vie des applications est un moyen essentiel pour les systèmes d'exploitation modernes de gérer les ressources. Sur Android, iOS et les versions récentes de Windows, le système d'exploitation peut lancer et arrêter les applications à tout moment. Cela permet à ces plates-formes de rationaliser et de réaffecter les ressources là où elles profitent le mieux à l'utilisateur.

Sur le Web, il n'y a toujours pas eu de cycle de vie de ce type, et les applications peuvent rester actives indéfiniment. Lorsqu'un grand nombre de pages Web est en cours d'exécution, les ressources système critiques telles que la mémoire, le processeur, la batterie et le réseau peuvent faire l'objet d'une sursouscription, ce qui nuit à l'expérience utilisateur.

Bien que la plate-forme Web contienne depuis longtemps des événements liés aux états du cycle de vie, tels que load, unload et visibilitychange, ces événements permettent uniquement aux développeurs 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 à faible consommation d'énergie (et qu'il soit plus attentif aux ressources en général sur toutes les plates-formes), les navigateurs doivent pouvoir récupérer et réaffecter de manière proactive les ressources système.

Aujourd'hui, les navigateurs prennent déjà activement des mesures pour préserver les ressources des pages situées dans les onglets en arrière-plan, et de nombreux navigateurs (en particulier Chrome) aimeraient que cela soit beaucoup plus efficace, afin de réduire l'utilisation globale des ressources.

Le problème est que les développeurs n'ont aucun moyen de se préparer à ces types d'interventions déclenchées par le système ni même de savoir si elles se produisent. Par conséquent, les navigateurs doivent être prudents, sinon les pages Web risquent de ne plus fonctionner.

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

  • Présentation et standardisation du concept des états du cycle de vie sur le Web
  • Définir de nouveaux états initiés par le système qui permettent aux navigateurs de limiter les ressources pouvant être utilisées par les onglets masqués ou inactifs.
  • Créer des API et des é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 les ressources système de manière plus agressive, ce qui profite à tous les internautes.

Le reste de cet article présente les nouvelles fonctionnalités du cycle de vie de la page, ainsi que leur lien avec tous les états et événements existants de la plate-forme Web. Il fournit également des recommandations et des bonnes pratiques concernant les types de tâches que les développeurs doivent (ou ne doivent pas) effectuer dans chaque état.

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

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

Le moyen le plus simple d'expliquer les états du cycle de vie de la page, ainsi que les événements qui signalent des transitions entre eux, est sans doute d'utiliser un schéma:

Représentation visuelle du flux d'état et d'événement décrit tout au long de ce document.
État de l'API Page Lifecycle et flux des événements.

États

Le tableau suivant explique en détail chaque état. Il répertorie également les états possibles qui peuvent se produire avant et après, ainsi que les événements que les développeurs peuvent utiliser pour observer les modifications.

État Description
Actif

Une page est à l'état active si elle est visible et qu'elle est ciblée en entrée.

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

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

Passif

Une page est à l'état passif si elle est visible et n'est pas ciblée en entrée.

États précédents possibles:
actif (via l'événement blur)
masqué (via l'événement visibilitychange)
gelé (via l'événement resume, puis l'événement }{21)/}{/22pageshow

États suivants possibles:
actif (via l'événement focus)
masqué (via l'événement visibilitychange)

Hidden

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

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

États suivants possibles:
passif (via l'événement visibilitychange)
arrêté (via l'événement freeze)
discarded (aucun événement déclenché)
arrêté (aucun événement déclenché)

Figé

À l'état Frozen, le navigateur suspend l'exécution des tâches gérables dans les files d'attente de tâches de la page jusqu'à ce que celle-ci se détache. Cela signifie que des é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 (surtout le rappel freeze), mais leur champ d'action et leur durée d'exécution peuvent être limités.

Les navigateurs figent les pages afin de préserver l'utilisation du processeur, de la batterie et des données. Cela permet également d'accélérer la navigation avant/avant, ce qui évite de devoir actualiser la page entière.

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

1 états suivants possibles:
active (via l'événement resume, puis l'événement pageshow)
passif resume, puis l'événement pageshow) ;
la carte masquée

resume

clôturé

Une page est à l'état arrêtée lorsqu'elle commence à être déchargée et effacée de la mémoire par le navigateur. Aucune nouvelle tâche ne peut démarrer dans cet état, et les tâches en cours peuvent être supprimées si elles s'exécutent trop longtemps.

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

États suivants possibles:
AUCUN

Supprimé

Une page est à l'état discarded (déchargée) lorsqu'elle est déchargée par le navigateur dans le but de conserver les ressources. Aucune tâche, aucun rappel d'événement ni aucun code JavaScript ne peut s'exécuter dans cet état, car les suppressions se produisent généralement en raison de contraintes de ressources et qu'il est impossible de démarrer de nouveaux processus.

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

États précédents possibles:
masqué (aucun événement déclenché)
gelé (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 signalent un possible changement de l'état du cycle de vie de la page. Le tableau suivant décrit tous les événements liés au cycle de vie, ainsi que les états depuis lesquels ils peuvent être transférés et vers lesquels ils peuvent être passés.

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 encore sélectionné d'entrée.

États précédents possibles:
passif

États actuels possibles:
actif

blur

Un élément DOM n'est plus sélectionné.

Remarque:Un événement blur ne signale pas nécessairement un changement d'état. Cela ne signale un changement d'état que si la page n'est plus sélectionnée en entrée (c'est-à-dire si la page n'a pas simplement basculé d'un élément à un autre).

États précédents possibles:
actif

États actuels possibles:
passif

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, minimise ou ferme le navigateur, ou change d'application sur un système d'exploitation mobile.

États précédents possibles:
passif
masqué

États actuels possibles:
passif
masqué

freeze *

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

États précédents possibles:
masqué

États actuels possibles:
gelé

resume *

Le navigateur a réactivé une page figée.

États précédents possibles:
gelé

États actuels possibles:
actif (s'il est suivi de l'événement pageshow)
passif (si suivi de l'événement pageshow)
masqué

pageshow

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

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 true. Sinon, la valeur est false.

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

États actuels possibles:
actif
passif
masqué

pagehide

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

Si l'utilisateur accède à une autre page et que le navigateur est en mesure d'ajouter la page actuelle au cache amélioré pour être réutilisée ultérieurement, la propriété persisted de l'événement est true. Lorsque la valeur est true, la page passe à l'état gelée. Sinon, elle passe à l'état arrêtée.

États précédents possibles:
masqué

États actuels possibles:
gelé (event.persisted est vrai, freeze événement suivi)
arrêté (event.persisted est "false", unload est suivi)

beforeunload

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

Important:L'événement beforeunload ne doit être utilisé que pour alerter l'utilisateur des modifications non enregistrées. Une fois ces modifications enregistrées, l'événement sera supprimé. Il ne doit jamais être ajouté sans conditions à la page, car cela pourrait nuire aux performances dans certains cas. Pour en savoir plus, consultez la section sur les anciennes API.

États précédents possibles:
masqué

États actuels possibles:
clôturé

unload

La page est en cours de déchargement.

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

États précédents possibles:
masqué

États actuels possibles:
clôturé

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

Nouvelles fonctionnalités ajoutées à Chrome 68

Le graphique précédent présente deux états déclenchés par le système plutôt que par l'utilisateur: gelé et supprimé. Comme indiqué précédemment, les navigateurs se figent et suppriment parfois des 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 libéré 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 dans Chrome pour ordinateur (la compatibilité avec Android fait l'objet d'un 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 de son chargement (remarque : les pages supprimées doivent être actualisé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 opérations importantes à effectuer dans les événements freeze et resume, ainsi que sur la gestion et la préparation des pages supprimées, consultez les recommandations pour les développeurs pour chaque état.

Les sections suivantes présentent la manière 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 d'une page dans le code

Avec 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 existantes de la plate-forme Web.

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

En revanche, les états gelé et arrêté 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 tous les changements d'é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 actions:

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

Notez que tous les écouteurs d'événements sont ajoutés à window et transmettent tous {capture: true}. Plusieurs raisons peuvent expliquer ce phénomène :

  • Tous les événements du cycle de vie de la 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 sur leurs éléments DOM respectifs.
  • La plupart de ces événements n'apparaissent pas dans des bulles, ce qui signifie qu'il est impossible d'ajouter des écouteurs d'événements qui ne capturent pas à un élément ancêtre commun et de les observer tous.
  • La phase de capture s'exécute avant les phases de cible ou de bulle. Par conséquent, l'ajout d'écouteurs permet de s'assurer qu'ils s'exécutent avant qu'un autre code ne puisse les annuler.

Recommandations pour les développeurs pour chaque état

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

Par exemple, il n'est clairement pas logique d'afficher une notification temporaire à l'utilisateur si la page est à l'état masqué. Bien que cet exemple soit assez évident, il existe d'autres recommandations moins évidentes qui méritent d'être énumérées.

État Recommandations pour les développeurs
Active

L'état active correspond au moment le plus critique pour l'utilisateur. C'est donc le moment le plus important pour que votre page soit réactive aux entrées utilisateur.

Toute tâche hors UI susceptible de bloquer le thread principal doit être définie comme prioritaire sur les périodes d'inactivité ou déchargées sur un nœud de calcul Web.

Passive

À l'état passif, l'utilisateur n'interagit pas avec la page, mais il peut tout de même la voir. Cela signifie que les mises à jour et les animations de l'interface utilisateur devraient toujours se dérouler sans heurts. Toutefois, la chronologie de ces mises à jour est moins importante.

Lorsque la page passe de active à passive, il est bon de conserver l'état d'application non enregistré.

Hidden

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

La transition vers masqué est souvent le dernier changement d'état observable de manière fiable par les développeurs. Cela est particulièrement vrai sur mobile, car les utilisateurs peuvent fermer des onglets ou le navigateur lui-même, et les événements beforeunload, pagehide et unload ne sont pas déclenchés dans ce cas.

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

Vous devez également cesser de mettre à jour l'interface utilisateur (puisqu'elles ne seront pas visibles par l'utilisateur) et arrêter toutes les tâches qu'un utilisateur ne souhaiterait pas exécuter en arrière-plan.

Frozen

À l'état gelée, les tâches figurant dans les files d'attente de tâches sont suspendues jusqu'à ce que la page soit libérée, ce qui peut ne jamais se produire (par exemple, si la page est supprimée).

Par conséquent, lorsque la page passe de masquée à figée, vous devez arrêter les minuteurs ou supprimer les connexions qui, si elles étaient figées, pourraient affecter les autres onglets ouverts de la même origine ou affecter la capacité du navigateur à placer la page dans le cache amélioré.

Il est particulièrement important que vous:

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

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

Terminated

En règle générale, aucune action n'est requise de votre part lorsqu'une page passe à l'état clôturé.

Étant donné que les pages déchargées à la suite d'une action de l'utilisateur passent toujours par l'état masqué avant de passer à l'état arrêté, c'est à l'état masqué que la logique de fin de session (par exemple, état de l'application persistante et création de rapports à l'analyse) doit être exécutée.

En outre (comme indiqué dans les recommandations concernant l'état masqué), il est très important pour les développeurs de comprendre que la transition vers l'état arrêté 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 d'événements d'arrêt (par exemple, beforeunload, pagehide et unload) risquent de perdre des données.

Discarded

L'état discarded n'est pas observable par les développeurs au moment où une page est supprimée. En effet, les pages sont généralement ignorées en raison des contraintes de ressources et, dans la plupart des cas, il est tout simplement impossible de débloquer une page pour permettre l'exécution du script en réponse à un événement de suppression.

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

Là encore, étant donné que la fiabilité et l'ordre des événements de cycle de vie ne sont pas mis en œuvre 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

Dans la mesure du possible, les événements suivants doivent être évités.

Événement "unload"

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 d'analyse, mais cela 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 la fermeture d'un onglet à partir du sélecteur d'onglets sur mobile ou la fermeture de l'application du 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 la fin d'une session, et de considérer l'état caché comme le dernier moment 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 précédents et suivants.

Dans tous les navigateurs récents, il est recommandé de toujours utiliser l'événement pagehide pour détecter les éventuels déchargements de page (c'est-à-dire l'état arrêté) plutôt que l'événement unload. Si vous devez assurer la compatibilité avec 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.
});

Événement beforeunload

L'événement beforeunload présente un problème semblable à l'événement unload. En effet, historiquement, la présence d'un événement beforeunload peut empêcher les pages d'être éligibles au cache amélioré. Les navigateurs récents ne sont pas soumis à cette restriction. Bien que certains navigateurs, par précaution, ne déclenchent pas l'événement beforeunload lorsque vous tentez de placer une page dans le cache amélioré, ce qui signifie que l'événement n'est pas fiable en tant que signal de fin de session. En outre, certains navigateurs (y compris Chrome) nécessitent une interaction de l'utilisateur sur la page avant d'autoriser le déclenchement de l'événement beforeunload, ce qui affecte 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 voulez avertir l'utilisateur que des modifications n'ont pas été enregistrées, il la perd s'il continue à décharger la page.

Étant donné que l'utilisation de beforeunload est justifiée, nous vous recommandons d'ajouter des écouteurs beforeunload uniquement lorsqu'un utilisateur a des modifications non enregistrées, puis de les supprimer immédiatement après leur enregistrement.

En d'autres termes, évitez de procéder ainsi (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.
    return (event.returnValue = true);
  }
});

Procédez plutôt comme suit (car l'écouteur beforeunload n'est ajouté que lorsque cela est nécessaire, et le supprime dans le cas contraire):

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

Questions fréquentes

Pourquoi l'état n'est-il pas "en cours de chargement" ?

L'API Page Lifecycle définit les états distincts 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 (ou même être arrêtée) avant la fin du chargement, un état de chargement distinct n'a aucun sens dans ce paradigme.

Ma page fonctionne lorsqu'elle est masquée. Comment puis-je éviter qu'elle ne soit figée ou supprimée ?

Il existe de nombreuses raisons légitimes pour lesquelles une page Web ne doit pas être figée lorsqu'elle est exécutée dans l'état masqué. L'exemple le plus évident est une application qui lit de la musique.

Dans certains cas, il est également risqué pour Chrome de supprimer une page, par exemple si elle contient un formulaire avec des entrées utilisateur non envoyées, ou si elle comporte un gestionnaire beforeunload qui avertit lorsque la page se décharge.

Pour le moment, Chrome sera prudent lors de la suppression de pages et ne le faites que s'il est certain que cela n'affectera pas les utilisateurs. Par exemple, les pages qui ont été observées pour effectuer l'une des actions suivantes alors qu'elles étaient dans l'état masqué ne seront pas supprimées, sauf en cas de contraintes extrêmes au niveau des ressources:

  • Lecture de l'audio
  • Utiliser WebRTC
  • Mettre à jour le titre d'une table ou le favicon
  • Affichage des alertes
  • Envoyer des notifications push

Pour connaître les fonctionnalités de liste actuelles qui permettent de déterminer si un onglet peut être figé ou supprimé en toute sécurité, consultez la section Heuristiques pour le gel et la suppression dans Chrome.

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

Le terme cache amélioré permet de décrire une optimisation de la navigation implémentée par certains navigateurs qui accélère l'utilisation des boutons "Précédent" et "Suivant".

Lorsqu'un utilisateur quitte une page, ces navigateurs figent une version de celle-ci afin qu'elle puisse être réactivée rapidement si l'utilisateur revient en arrière à 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.

À toutes les fins et pour tous les intents, ce gel est fonctionnellement identique à celui des navigateurs qui se figent pour préserver le processeur et la batterie. Pour cette raison, il est considéré comme faisant partie du cycle de vie gelé.

Si je ne peux pas exécuter d'API asynchrones à l'état figé ou arrêté, comment puis-je enregistrer des données dans IndexedDB ?

Dans les états "gelés" et "terminés", les tâches gelables des files d'attente de tâches d'une page sont suspendues, ce qui signifie que les API asynchrones et basées sur le rappel telles que IndexedDB ne peuvent pas être utilisées de manière fiable.

À l'avenir, nous ajouterons une méthode commit() aux objets IDBTransaction, ce qui permettra aux développeurs d'effectuer des transactions en écriture seule qui ne nécessitent pas de rappels. En d'autres termes, si le développeur se contente d'écrire des données dans IndexedDB et n'effectue pas de transaction complexe composée de lectures et d'écritures, la méthode commit() pourra se terminer avant la suspension des files d'attente de tâches (à condition que la base de données IndexedDB soit déjà ouverte).

Pour le code qui doit fonctionner aujourd'hui, les développeurs disposent de deux options:

  • Utilisez le stockage de session:le stockage de session est synchrone et conservé même si des pages sont supprimées.
  • Utilisez IndexedDB depuis votre service worker:un service worker peut stocker des données dans IndexedDB après l'arrêt ou la suppression de la page. Dans l'écouteur d'événements freeze ou pagehide, vous pouvez envoyer des données à votre service worker via postMessage(), qui se charge ensuite de les enregistrer.

Tester votre application à l'état "gelée" et "supprimée"

Pour tester le comportement de votre application lorsqu'elle est figée ou supprimée, vous pouvez accéder à chrome://discards pour figer ou supprimer l'un de vos onglets ouverts.

UI de Chrome supprimée
Interface utilisateur de suppression de 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 actualisées après une suppression.

Résumé

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

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