Événements du cycle de vie d'une page JavaScript
Découvrez les événements DOMContentLoaded, load, beforeunload et unload en JavaScript : quand ils se déclenchent, leurs différences et les alternatives modernes.
Chaque page ouverte par un navigateur passe par une séquence prévisible d'étapes : le HTML est analysé, les ressources externes sont téléchargées, l'utilisateur interagit, et finalement la page est détruite. JavaScript expose cette séquence à travers quatre événements du cycle de vie d'une page — DOMContentLoaded, load, beforeunload et unload. Savoir précisément quand chacun se déclenche vous permet d'exécuter du code d'initialisation au moment le plus tôt possible, de différer les traitements coûteux jusqu'à ce que tout soit prêt, et de protéger l'utilisateur contre la perte de données non sauvegardées.
Ce guide explique ce que signifie chaque événement, l'ordre dans lequel ils se déclenchent, les pièges courants, et les alternatives modernes pour les événements que les navigateurs déconseillent désormais. Tous les exemples ci-dessous sont exécutables — collez-les dans un fichier HTML ou ouvrez-les dans l'éditeur intégré.
Le cycle de vie d'une page en un coup d'œil
Les événements se déclenchent dans un ordre fixe. Les deux premiers surviennent au chargement de la page ; les deux derniers surviennent lorsque l'utilisateur quitte :
| Événement | Cible | Quand il se déclenche | Utilisation typique |
|---|---|---|---|
DOMContentLoaded | document | Le HTML est entièrement analysé ; les scripts s'exécutent ; les images/styles peuvent encore être en cours de chargement | Initialiser l'interface, attacher des écouteurs, interroger le DOM |
load | window | La page et toutes les sous-ressources (images, feuilles de style, iframes) ont fini de charger | Lire les dimensions des images, exécuter du code nécessitant que tout soit présent |
beforeunload | window | L'utilisateur est sur le point de quitter la page | Avertir en cas de modifications non sauvegardées |
unload | window | La page est en train d'être détruite (obsolète) | Nettoyage hérité / analytics |
Point clé à retenir : DOMContentLoaded est l'événement que vous voudrez utiliser la plupart du temps. Il se déclenche bien avant load, donc y attacher votre code rend la page interactive plus tôt.
Analyse approfondie de l'événement DOMContentLoaded
L'événement DOMContentLoaded se déclenche dès que le document HTML a été entièrement analysé, ce qui se produit généralement bien avant que les images, les feuilles de style et d'autres ressources externes n'aient été chargées. À ce moment-là, l'arbre DOM est complet, donc document.getElementById, querySelector et autres méthodes trouveront chaque élément écrit dans le HTML.
Comme il n'attend pas les images ni le CSS, vous devriez utiliser DOMContentLoaded chaque fois que votre script n'a besoin que de la structure DOM — ce qui est le cas de loin le plus courant.
Comment les scripts affectent DOMContentLoaded
Le navigateur suspend l'analyse HTML chaque fois qu'il rencontre une balise <script> ordinaire, exécute le script, puis continue. Cela signifie que DOMContentLoaded attend les scripts synchrones. Deux nuances importantes sont à noter :
<script async>s'exécute dès qu'il est téléchargé et ne bloque pasDOMContentLoaded.<script defer>s'exécute après l'analyse du document mais avant le déclenchement deDOMContentLoaded, dans l'ordre du document.
Si vous contrôlez le timing des scripts avec ces attributs, consultez scripts : async, defer pour une vision complète.
Vérifier l'état avec document.readyState
Si votre code peut s'exécuter après que le DOM a déjà été analysé (par exemple, un script ajouté dynamiquement), l'écouteur ne se déclencherait jamais car l'événement s'est déjà produit. Protégez-vous contre ce cas avec document.readyState :
function onReady() {
console.log('DOM is ready, current state:', document.readyState);
}
if (document.readyState === 'loading') {
// Still parsing — wait for the event.
document.addEventListener('DOMContentLoaded', onReady);
} else {
// 'interactive' or 'complete' — DOM is already ready.
onReady();
}readyState passe par trois valeurs : "loading" pendant l'analyse, "interactive" une fois que le DOM est prêt (c'est lorsque DOMContentLoaded se déclenche), et "complete" une fois que tout, y compris les ressources, a été chargé (c'est lorsque load se déclenche).
Exemple interactif : DOMContentLoaded en action
Pour voir DOMContentLoaded en action, l'exemple suivant met à jour le contenu d'un élément div une fois que le document HTML est entièrement analysé, mais avant que la page entière ne soit complètement chargée.
<!DOCTYPE html>
<html lang="en">
<head>
<title>DOMContentLoaded Example</title>
</head>
<body>
<div id="output">Waiting for DOM...</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('output').innerHTML = 'DOM fully loaded and parsed!'
});
</script>
</body>
</html>Cet exemple peut être collé dans n'importe quel fichier HTML et visualisé dans un navigateur pour observer à quelle vitesse DOMContentLoaded se déclenche par rapport au chargement complet de la page.
Exploration de l'événement load
L'événement load est essentiel pour les opérations qui nécessitent que la page web entière soit complètement chargée, y compris toutes les ressources dépendantes comme les images et les feuilles de style. Au moment où load se déclenche, chaque image a ses dimensions réelles, les polices sont appliquées et les iframes sont chargées — c'est donc l'endroit idéal pour le code qui mesure la page rendue.
Le compromis est une question de timing : une seule grande image ou un widget tiers lent retarde load pour toute la page. C'est pourquoi vous devriez réserver load pour le travail qui dépend réellement des ressources, et garder l'initialisation ordinaire sur DOMContentLoaded. Pour le chargement et la gestion des erreurs de ressources individuelles (plutôt que de la page entière), consultez chargement de ressources : onload et onerror.
Exemple interactif : Démonstration de l'événement load
Ici, nous créons un exemple où un message s'affiche uniquement après que tout sur la page est complètement chargé. Comme vous pouvez le voir, l'événement DOMContentLoaded survient toujours avant l'événement load.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load Event Example</title>
</head>
<body>
<div>You see first triggered event on top of the other.</div>
<script>
window.addEventListener('load', function() {
const newDiv = document.createElement("div");
newDiv.innerHTML = 'loaded event happened!'
document.body.append(newDiv);
});
window.addEventListener('DOMContentLoaded', function() {
const newDiv = document.createElement("div");
newDiv.innerHTML = 'DOMContentLoaded event happened!'
document.body.append(newDiv);
});
</script>
</body>
</html>Copiez et testez ce code dans votre propre environnement HTML pour voir la différence de timing entre DOMContentLoaded et load.
Gestion de l'événement beforeunload
L'événement beforeunload est extrêmement utile pour prévenir la perte de données, en avertissant les utilisateurs avant qu'ils ne quittent une page qui pourrait avoir des modifications non sauvegardées. Lorsqu'un gestionnaire définit event.returnValue, le navigateur affiche une boîte de dialogue de confirmation générique (« Quitter le site ? Les modifications que vous avez apportées ne seront peut-être pas enregistrées »).
Quelques règles que les navigateurs appliquent désormais, à connaître avant de vous y fier :
- Le message personnalisé est ignoré. Pour éviter le spam, les navigateurs affichent leur propre texte indépendamment de la chaîne que vous assignez. Définir
returnValueà n'importe quelle valeur non vide (ou appelerevent.preventDefault()) suffit à déclencher la boîte de dialogue. - La boîte de dialogue n'apparaît que si l'utilisateur a interagi avec la page (cliqué, tapé, etc.). Une page que l'utilisateur n'a jamais touchée ne peut pas bloquer la navigation.
- N'enregistrez le gestionnaire que lorsqu'il y a réellement des modifications non sauvegardées, et supprimez-le une fois les données sauvegardées. Un gestionnaire
beforeunloadpermanent agace les utilisateurs et peut nuire aux performances du cache de navigation avant/arrière.
Un modèle plus robuste ajoute et supprime l'écouteur en fonction d'un indicateur de modification :
let isDirty = false;
function beforeUnloadHandler(event) {
event.preventDefault();
// Required for some browsers to show the dialog.
event.returnValue = '';
}
function markDirty() {
if (!isDirty) {
isDirty = true;
window.addEventListener('beforeunload', beforeUnloadHandler);
}
}
function markSaved() {
isDirty = false;
window.removeEventListener('beforeunload', beforeUnloadHandler);
}Exemple interactif : Implémentation d'une confirmation beforeunload
Cet exemple invite l'utilisateur avec une boîte de dialogue de confirmation lorsqu'il tente de quitter la page, ce qui aide à éviter la perte accidentelle de données.
<!DOCTYPE html>
<html lang="en">
<head>
<title>beforeunload Example</title>
</head>
<body>
<p>Now if you want to exit this page, a confirmation alert will be shown as a result of the <code>beforeunload</code> event.</p>
<script>
window.addEventListener('beforeunload', function(event) {
event.returnValue = '';
});
</script>
</body>
</html>Testez ce code en accédant à la page « essayez vous-même » puis en essayant de naviguer vers une autre page.
Utilisation de l'événement unload
L'événement unload est obsolète et vous ne pourrez pas l'utiliser dans la plupart des navigateurs modernes. Il est également considéré comme une mauvaise pratique. Cette section existe donc uniquement pour mieux comprendre les codes hérités.
Bien que moins couramment utilisé en raison des restrictions des navigateurs modernes et de l'essor des applications monopages, l'événement unload s'exécutait historiquement lorsqu'une page était en train d'être détruite — utile pour nettoyer des ressources ou envoyer un dernier ping analytics. Le problème est que unload (et beforeunload) empêche le navigateur de stocker la page dans le cache avant/arrière (bfcache), ce qui ralentit la navigation par le bouton retour pour tout le monde.
Alternatives modernes : visibilitychange et pagehide
Au lieu de unload, écoutez visibilitychange et traitez la transition vers "hidden" comme le dernier moment fiable pour persister l'état. Cela se déclenche de manière cohérente sur ordinateur et mobile, y compris lorsque l'utilisateur change d'onglet ou ferme l'application :
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
// Last reliable point to save state.
console.log('Page hidden — flush analytics / save draft here');
}
});Pour envoyer des données à la fermeture, utilisez navigator.sendBeacon(), qui met en file d'attente une requête qui survit à la fermeture de la page :
function sendStats(data) {
navigator.sendBeacon('/log', JSON.stringify(data));
}Exemple interactif : Utilisation de l'événement unload
Ce code affiche un message d'alerte lorsque la page est en cours de déchargement. Il est obsolète comme mentionné, et ne fonctionne pas dans la plupart des navigateurs modernes — préférez visibilitychange ci-dessus.
<!DOCTYPE html>
<html lang="en">
<head>
<title>unload Example</title>
</head>
<body>
<script>
window.addEventListener('unload', function(event) {
alert('Page is unloading...');
// Perform cleanup tasks or analytics here
});
</script>
</body>
</html>Conclusion
Chacun de ces événements correspond à une phase spécifique du cycle de vie d'une page web, du chargement initial au déchargement final. Les conseils pratiques sont simples :
- Exécutez la plupart des initialisations sur
DOMContentLoaded— il se déclenche le plus tôt et le DOM est prêt. - Utilisez
loaduniquement lorsque vous dépendez de la présence complète des images, polices ou autres sous-ressources. - Utilisez
beforeunloadpour protéger les modifications non sauvegardées, et n'ajoutez l'écouteur que lorsque les données sont modifiées. - Évitez
unload; privilégiezvisibilitychangeassocié ànavigator.sendBeacon().
Pour aller plus loin, explorez ces chapitres connexes :
- Introduction aux événements du navigateur
- Scripts : async, defer
- Chargement de ressources : onload et onerror
- Environnement navigateur et spécifications