L'exécution de JavaScript au sein d'un navigateur web repose sur trois piliers fondamentaux : le Modèle Objet du Navigateur (BOM), le Modèle Objet de Document (DOM) et ECMAScript. Tandis qu'ECMAScript fournit les bases logiques et la manipulation des données, le BOM et le DOM se concentrent sur l'interaction avec l'environnement du navigateur et le contenu de la page web.
- ECMAScript : Gère la logique fondamentale et le traitement des données.
- DOM (Document Object Model) : Permet l'interaction avec le contenu et la structure du document HTML affiché dans la fenêtre du navigateur.
- BOM (Browser Object Model) : Offre des méthodes pour interagir avec les fonctionnalités intrinsèques du navigateur, comme la fenêtre, l'historique de navigation et l'URL.
Le BOM fournit des interfaces pour manipuler les éléments du navigateur tels que les fenêtres, l'historique de navigation, tandis que le DOM représente la structure du contenu web, permettant de modifier les éléments de la page.
Modèle Objet du Navigateur (BOM)
L'Objet location
L'objet location, accessible via window.location ou simplement location, est une interface essentielle en JavaScript qui permet d'accéder et de modifier l'URL du document courant. Il est particulièrement utile pour la navigation et l'analyse d'URL.
Propriétés Courantes :
location.href: L'URL complète de la page actuelle, par exemple"https://www.monsite.fr/recherche?categorie=web#section"ou"localhost:8080"..origin: Le protocole, l'hôte et le port de l'URL, par exemple"https://www.monsite.fr"..protocol: Le protocole de l'URL, par exemple"https:"..host: Le nom d'hôte (domaine) et le port (s'il est spécifié), par exemple"www.monsite.fr"ou"localhost:8080"..hostname: Le nom d'hôte sans le port, par exemple"www.monsite.fr"ou"localhost"..port: Le numéro de port, par exemple"8080"(souvent vide pour les ports par défaut 80/443)..pathname: Le chemin du fichier ou de la ressource, par exemple"/recherche/index/..."..search: La chaîne de requête (paramètres après?), par exemple"?categorie=web"..hash: Le fragment d'URL (identifiant après#), par exemple"#section". Utilisé notamment dans les routes de type "hash".
Méthodes Utiles :
// Recharger la page actuelle.
// Si `forceReload` est vrai, la page est rechargée depuis le serveur sans utiliser le cache.
location.reload(true); // Équivalent à window.location.reload(true)
// Remplacer l'URL actuelle par une nouvelle, sans créer une nouvelle entrée dans l'historique du navigateur.
// L'utilisateur ne pourra pas revenir à la page précédente via le bouton "précédent".
location.replace('https://www.nouvellesite.com');
// Charger une nouvelle URL et l'ajouter à l'historique du navigateur.
// L'utilisateur pourra revenir à la page précédente.
location.assign('https://www.nouvellesite.com');
L'Objet history
L'API History de HTML5 permet de manipuler l'historique de session du navigateur, offrant aux développeurs un contrôle fin sur la navigation sans rechargement complet de la page. C'est un élément clé pour les applications monopages (SPA).
history.state: Un objet en lecture seule qui représente l'état de la page actuelle.history.pushState(etat, titre, url): Ajoute une nouvelle entrée à l'historique de session.etat: Un objet qui sera associé à la nouvelle entrée d'historique. Cet objet sera disponible viahistory.stateet dans l'événementpopstate.titre: Un titre pour la nouvelle entrée d'historique (actuellement ignoré par la plupart des navigateurs).url: L'URL de la nouvelle entrée. Elle doit être du même domaine que la page actuelle.
history.replaceState(etat, titre, url): Modifie l'entrée actuelle de l'historique, sans en ajouter une nouvelle.
// Ajoute une entrée dans l'historique
history.pushState({ identifiant: 1 }, 'Page 1', '?page=1');
// L'URL affiche maintenant : http://exemple.com/page.html?page=1
history.pushState({ identifiant: 2 }, 'Page 2', '?page=2');
// L'URL affiche maintenant : http://exemple.com/page.html?page=2
// Remplace l'entrée actuelle de l'historique
history.replaceState({ identifiant: 3 }, 'Page 3', '?page=3');
// L'URL affiche maintenant : http://exemple.com/page.html?page=3 (l'entrée "?page=2" a été remplacée)
// Revient à l'entrée précédente
history.back();
// L'URL affiche : http://exemple.com/page.html?page=1
// Revient une nouvelle fois en arrière
history.back();
// L'URL affiche : http://exemple.com/page.html
// Avance de deux entrées dans l'historique
history.go(2);
// L'URL affiche : http://exemple.com/page.html?page=3
Comparaison entre les Modes de Routage History et Hash
Mode Hash :
Le mode hash utilise le fragment d'URL (la partie après le #) pour gérer le routage frontal. Chaque modification de ce fragment ne déclenche pas un rechargement de page, car le navigateur considère que c'est toujours la même ressource.
- La navigation est basée sur la modification de
location.hash. - Les changements sont détectés via l'événement
hashchange. - Ne provoque pas de requêtes HTTP au serveur pour les changements de route, évitant ainsi les rechargements de page.
window.addEventListener('hashchange', function() {
console.log('Le hash a été modifié.');
console.log('Événement hashchange déclenché.');
});
L'événement popstate est également déclenché lors des changements de hash si l'historique du navigateur est manipulé (par exemple, via les boutons retour/avant). Cependant, popstate est principalement associé à l'API History (pushState/replaceState).
window.addEventListener("popstate", () => {
console.log("Événement popstate déclenché.");
});
Différences Clés :
- Apparence de l'URL :
- Hash : Contient un
#, par exemplewww.monsite.com/#/chemin. Moins esthétique. - History : Ne contient pas de
#, par exemplewww.monsite.com/chemin. Plus propre.
- Hash : Contient un
- Principe de Fonctionnement :
- Hash : Utilise la modification de
location.hashet l'événementhashchange. - History : S'appuie sur l'API History (
pushState,replaceState) et l'événementpopstate. Ces méthodes permettent de manipuler l'historique du navigateur sans recharger la page.
- Hash : Utilise la modification de
- Cas d'Usage :
- Hash : Peut poser problème avec certains services de partage qui interprètent le
#comme une ancre interne plutôt qu'une partie de la route. - History : Nécessite une configuration serveur spécifique pour gérer les rafraîchissements de page ou l'accès direct à une route. Sans cette configuration, le serveur pourrait renvoyer une erreur 404, car il ne trouve pas de ressource correspondant à l'URL.
- Hash : Peut poser problème avec certains services de partage qui interprètent le
- Compatibiilté :
- Hash : Largement compatible (IE8+).
- History : Compatible avec les navigateurs modernes (IE10+, car c'est une API HTML5 plus récente).
Résoudre les Erreurs 404 en Mode History :
Pour éviter les erreurs 404 lors du rafraîchissement d'une page configurée en mode History, il est impératif de configurer le serveur web. Si l'URL ne correspond à aucune ressource physique, le serveur doit être instruit de rediriger toutes les requêtes vers le fichier index.html (ou le point d'entrée de votre SPA).
Exemple de configuration avec Nginx :
server {
listen 80;
server_name votredomaine.com;
location / {
root /chemin/vers/votre/app/dist; // Le répertoire où sont stockés les fichiers de votre application
index index.html;
try_files $uri $uri/ /index.html; // Essaye de servir le fichier demandé, sinon redirige vers index.html
}
}
Cette configuration indique à Nginx de d'abord chercher un fichier ou un répertoire correspondant à l'URI. Si rien n'est trouvé, il renvoie index.html, permettant à l'application JavaScript de gérer le routage côté client.
L'Objet navigator
L'objet navigator fournit des informations sur le navigateur de l'utilisateur et l'environnement du système. Il est couramment utilisé pour détecter le type de navigateur, le système d'exploitation, et les capacités du périphérique.
navigator.userAgent: Une chaîne qui identifie le navigateur de l'utilisateur (utile pour des détections de compatibilité ou d'optimisations).
function detecteurNavigateur() {
const agentUtilisateur = navigator.userAgent;
let nomNavigateur;
if (agentUtilisateur.includes("Chrome") && !agentUtilisateur.includes("Edg")) {
nomNavigateur = "Google Chrome";
} else if (agentUtilisateur.includes("Firefox")) {
nomNavigateur = "Mozilla Firefox";
} else if (agentUtilisateur.includes("Safari") && !agentUtilisateur.includes("Chrome")) {
nomNavigateur = "Apple Safari";
} else if (agentUtilisateur.includes("Edg")) {
nomNavigateur = "Microsoft Edge";
} else if (agentUtilisateur.includes("Opera") || agentUtilisateur.includes("OPR")) {
nomNavigateur = "Opera";
} else if (agentUtilisateur.includes("MSIE") || agentUtilisateur.includes("Trident")) {
nomNavigateur = "Internet Explorer";
} else {
nomNavigateur = "Navigateur Inconnu";
}
return nomNavigateur;
}
console.log(`Vous utilisez : ${detecteurNavigateur()}`);
L'objet navigator est également utilisé pour accéder à des APIs spécifiques comme navigator.clipboard (presse-papiers) ou navigator.mediaDevices (accès aux médias).
L'Objet screen
L'objet screen fournit des informations sur l'écran physique de l'utilisateur. Il est utile pour les ajustements de l'interface utilisateur en fonction des dimensions disponibles.
Les propriétés suivantes ne sont PAS affectées par le niveau de zoom de la page :
screen.width: Largeur totale de l'écran en pixels.screen.height: Hauteur totale de l'écran en pixels.screen.availWidth: Largeur disponible de l'écran, excluant les barres de tâches ou les docks système.screen.availHeight: Hauteur disponible de l'écran, excluant les barres de tâches ou les docks système.screen.colorDepth: Nombre de bits utilisés pour afficher une couleur sur l'écran (généralement 24 pour le "vrai" couleur).screen.pixelDepth: Similaire àcolorDepth, représente la profondeur de couleur réelle.
Propriétés JavaScript pour les Dimensions
Comprendre les différentes propriétés JavaScript pour les dimensions est crucial pour le positionnement et l'ajustement des éléments.
Dimensions de la Fenêtre du Navigateur :
window.innerWidth: La largeur de la zone d'affichage (viewport) de la fenêtre du navigateur, y compris les barres de défilement verticales. Cette valeur change avec le zoom.window.innerHeight: La hauteur de la zone d'affichage (viewport) de la fenêtre du navigateur, y compris les barres de défilement horizontales. Cette valeur change avec le zoom.window.outerWidth: La largeur totale de la fenêtre du navigateur, y compris les cadres et les barres d'outils. Cette valeur ne change pas avec le zoom.window.outerHeight: La hauteur totale de la fenêtre du navigateur, y compris les cadres et les barres d'outils. Cette valeur ne change pas avec le zoom.
Dimensions des Éléments (el) :
Ces propriétés changent avec le zoom de la page.
el.offsetWidth: La largeur totale de l'élément, y compris son contenu, son padding et sa bordure.el.offsetHeight: La hauteur totale de l'élément, y compris son contenu, son padding et sa bordure.el.offsetLeft: La psoition horizontale de l'élément par rapport au bord gauche de son conteneur de décalage (offset parent).el.offsetTop: La position verticale de l'élément par rapport au bord supérieur de son conteneur de décalage.
Propriétés liées au client (zone de contenu visible) :
el.clientWidth: La largeur de la zone visible de l'élément, y compris le padding mais sans la bordure ni la barre de défilement verticale.el.clientHeight: La hauteur de la zone visible de l'élément, y compris le padding mais sans la bordure ni la barre de défilement horizontale.el.clientTop: La largeur de la bordure supérieure de l'élément.el.clientLeft: La largeur de la bordure gauche de l'élément.
Propriétés liées au défilement (scroll) :
el.scrollWidth: La largeur totale du contenu de l'élément, y compris le contenu non visible et le padding.el.scrollHeight: La hauteur totale du contenu de l'élément, y compris le contenu non visible et le padding.el.scrollLeft: La distance en pixels du bord gauche du contenu actuellement défilé horizontalement.el.scrollTop: La distance en pixels du bord supérieur du contenu actuellement défilé verticalement.
Pour obtenir des informations complètes sur la taille et la position d'un élément par rapport à la zone d'affichage, utilisez :
const elementRect = el.getBoundingClientRect();
console.log(elementRect.top); // Distance du bord supérieur de la viewport
console.log(elementRect.left); // Distance du bord gauche de la viewport
console.log(elementRect.bottom); // Distance du bord inférieur de la viewport
console.log(elementRect.right); // Distance du bord droit de la viewport
console.log(elementRect.width); // Largeur de l'élément (équivalent à offsetWidth)
console.log(elementRect.height); // Hauteur de l'élément (équivalent à offsetHeight)
Modèle Objet de Document (DOM) — Gestion des Événements
Sélectionner des Éléments : document.getElementById, querySelector, etc.
JavaScript offre plusieurs méthodes pour accéder et manipuler les éléments d'un document HTML. Voici les plus courantes :
// Sélection par ID
const elementParId = document.getElementById("monIdUnique");
// Sélection par nom de classe
const elementsParClasse = document.getElementsByClassName("maClasse"); // Retourne une HTMLCollection (live)
// Sélection par nom de balise
const elementsParTag = document.getElementsByTagName("div"); // Retourne une HTMLCollection (live)
// Sélectionne le premier élément correspondant à un sélecteur CSS
const premierElement = document.querySelector("#identifiantUtilisateur"); // Par ID
const autreElement = document.querySelector(".boutonActif"); // Par classe
const elementParent = document.querySelector("section > article"); // Par sélecteur CSS complexe
// Sélectionne tous les éléments correspondant à un sélecteur CSS
const tousLesElements = document.querySelectorAll(".itemListe"); // Retourne une NodeList (statique)
// Exemple d'utilisation de querySelectorAll avec Array.prototype.forEach
const boutonsDeCouleur = document.querySelectorAll('.bouton-couleur');
Array.prototype.forEach.call(boutonsDeCouleur, function(bouton) {
bouton.addEventListener('click', function() {
console.log(`Bouton ${bouton.textContent} cliqué !`);
});
});
Ajouter des Écouteurs d'Événements : addEventListener()
La méthode addEventListener() est la manière préférée d'attacher des gestionnnaires d'événements à des éléments. Elle permet d'attacher plusieurs fonctions de rappel à un même événement sur un même élément, sans écraser les gestionnaires existants.
const monBouton = document.querySelector('.action-bouton');
// Ajoute un premier gestionnaire d'événement
monBouton.addEventListener('click', function() {
console.log('Première action exécutée !');
});
console.log('Le script continue son exécution.'); // Cette ligne s'affiche immédiatement
// Ajoute un second gestionnaire d'événement
monBouton.addEventListener('click', function() {
console.log('Seconde action exécutée !');
});
Lorsque monBouton est cliqué, les deux messages "Première action exécutée !" et "Seconde action exécutée !" s'afficheront séquentiellement.
Désabonnement d'Événements
Pour désactiver un gestionnaire d'événements (par exemple, après une seule utilisation), on peut attribuer null à la propriété onclick ou utiliser removeEventListener.
const boutonUnique = document.querySelector(".btn-once");
boutonUnique.onclick = function() {
console.log("Action unique déclenchée !");
boutonUnique.onclick = null; // Désactive le gestionnaire après le premier clic
};
Flux des Événements : Capture et Propagation (Bubbling)
Lorsqu'un événement est déclenché sur un élément, il traverse le DOM en trois phases :
- Phase de Capture : L'événement se propage de l'objet
windowvers l'élément cible. - Phase Cible : L'événement atteint l'élément qui l'a déclenché.
- Phase de Propagation (Bubbling) : L'événement remonte de l'élément cible vers l'objet
window.
La méthode addEventListener(type, listener, options) ou addEventListener(type, listener, useCapture) permet de spécifier à quelle phase le gestionnaire doit s'exécuter. Le troisième argument useCapture (ou l'option capture dans l'objet options) détermine cela :
- Si
true(ou{ capture: true }), le gestionnaire est déclenché pendant la phase de capture. - Si
false(ou omis), le gestionnaire est déclenché pendant la phase de propagation.
<div id="conteneurBleu" style="padding: 20px; background-color: lightblue;">
Bleu
<div id="conteneurJaune" style="padding: 20px; background-color: lightyellow;">
Jaune
<div id="conteneurVert" style="padding: 20px; background-color: lightgreen;">
Vert
</div>
</div>
</div>
<script>
const conteneurBleu = document.getElementById('conteneurBleu');
const conteneurJaune = document.getElementById('conteneurJaune');
const conteneurVert = document.getElementById('conteneurVert');
// Gestionnaires en phase de propagation (bubbling - par défaut)
conteneurBleu.addEventListener('click', () => { console.log('Clic sur Bleu (Bubbling)'); });
conteneurJaune.addEventListener('click', () => { console.log('Clic sur Jaune (Bubbling)'); });
conteneurVert.addEventListener('click', () => { console.log('Clic sur Vert (Bubbling)'); });
// Gestionnaires en phase de capture
conteneurBleu.addEventListener('click', () => { console.log('Clic sur Bleu (Capture)'); }, true);
conteneurJaune.addEventListener('click', () => { console.log('Clic sur Jaune (Capture)'); }, true);
conteneurVert.addEventListener('click', () => { console.log('Clic sur Vert (Capture)'); }, true);
</script>
Si vous cliquez sur "Vert" :
- Capture : "Clic sur Bleu (Capture)" -> "Clic sur Jaune (Capture)" -> "Clic sur Vert (Capture)"
- Propagation : "Clic sur Vert (Bubbling)" -> "Clic sur Jaune (Bubbling)" -> "Clic sur Bleu (Bubbling)"
Délégation d'Événements
La délégation d'événements est une technique qui consiste à n'attacher qu'un seul gestionnaire d'événements à un élément parent, plutôt qu'à chaque élément enfant individuellement. Elle repose sur la phase de propagation des événements et offre des avantages en termes de performance et de gestion de code, notamment pour les listes dynamiques.
<ul id="listeDynamique">
<li>Élément 1</li>
<li>Élément 2</li>
<li>Élément 3</li>
</ul>
<script>
const liste = document.getElementById("listeDynamique");
liste.addEventListener("click", (event) => {
// Vérifie si l'élément cliqué (event.target) est bien un LI
if (event.target.tagName === 'LI') {
console.log(`Vous avez cliqué sur : ${event.target.textContent}`);
// event.target fait référence à l'élément LI qui a été cliqué
// event.currentTarget fait référence à l'élément UL (l'écouteur)
}
});
// Ajouter un nouvel élément après le chargement - il fonctionnera avec la délégation
setTimeout(() => {
const nouvelElement = document.createElement('li');
nouvelElement.textContent = 'Nouvel Élément Dynamique';
liste.appendChild(nouvelElement);
}, 2000);
</script>
Contrôler le Flux des Événements
1. Empêcher la Propagation de l'Événement (Bubbling/Capture)
La méthode event.stopPropagation() empêche l'événement de se propager davantage dans le DOM, que ce soit en phase de capture ou de propagation. Les autres gestionnaires attachés au même élément pour le même événement sont toujours exécutés.
const enfant = document.getElementById('elementEnfant');
enfant.addEventListener('click', (event) => {
event.stopPropagation(); // L'événement ne remontera pas au parent
console.log('Clic sur l\'enfant, propagation stoppée.');
});
2. Empêcher le Comportement par Défaut du Navigateur
La méthode event.preventDefault() annule l'action par défaut associée à l'événement. Par exemple, un clic sur un lien ne provoquera pas de navigation, et un envoi de formulaire ne rechargera pas la page.
<a href="https://www.google.com" id="lienSansNavigation">Aller sur Google (pas vraiment)</a>
<script>
const lien = document.getElementById('lienSansNavigation');
lien.addEventListener('click', (event) => {
event.preventDefault(); // Annule la navigation par défaut
console.log('Navigation vers Google empêchée.');
});
</script>
3. Empêcher la Propagation Immédiate et les Autres Gestionnaires
La méthode event.stopImmediatePropagation() non seulement empêche l'événement de se propager aux éléments parents, mais elle empêche également l'exécution de tout autre gestionnaire d'événements attaché au même élément pour le même type d'événement.
const monElement = document.getElementById('monElement');
monElement.addEventListener('click', (event) => {
event.stopImmediatePropagation();
console.log('Premier gestionnaire exécuté, arrêt immédiat.');
});
monElement.addEventListener('click', (event) => {
console.log('Deuxième gestionnaire ne sera jamais exécuté.');
});
L'Objet event
Lorsqu'un événement se produit, le navigateur crée un objet Event qui contient des informations détaillées sur l'événement. Cet objet est passé comme premier argument aux fonctions de rappel des écouteurs d'événements.
Propriétés et méthodes courantes de l'objet Event :
event.type: Le type de l'événement (ex:"click","mouseover").event.target: L'élément DOM sur lequel l'événement a été initialement déclenché.event.currentTarget: L'élément DOM sur lequel l'écouteur d'événement a été attaché.event.preventDefault(): Annule l'action par défaut du navigateur.event.stopPropagation(): Empêche la propagation de l'événement.event.clientX,event.clientY: Coordonnées X et Y de la souris par rapport à la zone d'affichage.event.screenX,event.screenY: Coordonnées X et Y de la souris par rapport à l'écran.event.keyCode(déprécié),event.key,event.code: Informations sur la touche pressée pour les événements clavier.
Types d'Événements Courants
- Événements Souris :
click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave. - Événements Clavier :
keydown,keyup,keypress(déprécié). - Événements Formulaires :
submit,focus,blur,change,input. - Événements Tactiles (mobiles) :
touchstart,touchmove,touchend. - Événements de Chargement :
load(pour page/image),unload,DOMContentLoaded(HTML chargé et analysé). - Autres Événements :
resize(fenêtre),scroll(page),error(ressources),animationend,transitionend(CSS).
Exemple d'utilisation de addEventListener avec Vue.js (API Composition) :
<template>
<div>
<h1>Fenêtre Redimensionnée : {{ dimensionsFenetre.largeur }}x{{ dimensionsFenetre.hauteur }}</h1>
</div>
</template>
<script>
import { ref, onMounted, onUnmounted } from 'vue';
export default {
name: 'MonComposantReactif',
setup() {
const dimensionsFenetre = ref({ largeur: window.innerWidth, hauteur: window.innerHeight });
const gestionnaireRedimensionnement = () => {
dimensionsFenetre.value.largeur = window.innerWidth;
dimensionsFenetre.value.hauteur = window.innerHeight;
console.log(`Fenêtre redimensionnée à : ${window.innerWidth}x${window.innerHeight}`);
};
onMounted(() => {
// Ajoute l'écouteur d'événement après le montage du composant
window.addEventListener('resize', gestionnaireRedimensionnement);
});
onUnmounted(() => {
// Supprime l'écouteur d'événement avant la destruction du composant
window.removeEventListener('resize', gestionnaireRedimensionnement);
});
return {
dimensionsFenetre
};
},
};
</script>
<style scoped>
/* Styles du composant */
div {
padding: 20px;
background-color: #f0f0f0;
border-radius: 8px;
text-align: center;
}
</style>
Interaction Réseau - XMLHttpRequest
L'objet XMLHttpRequest (XHR) est une API JavaScript utilisée pour envoyer des requêtes HTTP asynchrones au serveur. Il est la base de nombreuses interactions réseau côté client avant l'avènement de l'API Fetch.
const requeteXHR = new XMLHttpRequest();
requeteXHR.open('GET', '/api/donnees', true); // Méthode, URL, Asynchrone
requeteXHR.setRequestHeader('Content-Type', 'application/json'); // Définir les en-têtes
requeteXHR.onreadystatechange = () => {
if (requeteXHR.readyState === 4) { // Requête terminée et réponse prête
if (requeteXHR.status >= 200 && requeteXHR.status < 300) { // Succès
console.log('Réponse du serveur:', JSON.parse(requeteXHR.responseText));
} else { // Erreur
console.error('Erreur lors de la requête:', requeteXHR.status);
}
}
};
requeteXHR.onerror = () => { // Gestion des erreurs réseau
console.error('Erreur réseau.');
};
requeteXHR.timeout = 5000; // Définir un délai d'attente de 5 secondes
requeteXHR.ontimeout = () => {
console.error('La requête a expiré.');
};
requeteXHR.send(); // Envoyer la requête
Concepts Clés liés aux requêtes XHR et HTTP :
- Principes RESTful : Comprendre les méthodes HTTP (GET, POST, PUT, DELETE, OPTIONS) et leur utilisation dans les APIs REST.
- CORS (Cross-Origin Resource Sharing) : Mécanisme de sécurité qui contrôle la façon dont les ressources d'un domaine peuvent être demandées par une page web d'un autre domaine.
- Codes de Statut HTTP : Connaître les différentes catégories (1xx Informational, 2xx Success, 3xx Redirection, 4xx Client Error, 5xx Server Error), en particulier
304 Not Modified, qui est lié au cache du navigateur. - Cache Navigateur :
- Cache Fort (Strong Cache) : Le navigateur ne demande pas au serveur si la ressource a changé (via
ExpiresouCache-Control). - Cache Négocié (Weak/Conditional Cache) : Le navigateur demande au serveur si la ressource a changé avant de la réutiliser (via
ETagouLast-Modified). Si le serveur répond304 Not Modified, le cache local est utilisé.
- Cache Fort (Strong Cache) : Le navigateur ne demande pas au serveur si la ressource a changé (via