Démystifier la comparaison du Virtual DOM : ce que React compare et pourquoi c’est avantageux
Comprendre ce qu’est réellement le Virtual DOM de React, comment la phase de conciliation compare deux arbres d’éléments, quels sont les changements lors de la phase d’enregistrement, et d’où proviennent les avantages en termes de performance.
Les interfaces changent constamment : une notification apparaît, un bouton se commute, un compteur avance, une liste est réaffichée. Chaque changement de ce type doit parvenir au DOM du navigateur, et mettre à jour le DOM de manière imprudente est un moyen fiable de rendre une page lente. La solution de React consiste en un DOM virtuel accompagné d’une étape de comparaison appelée réconciliation. Cet article explique ce que React conserve en mémoire, comment il détermine ce qui a changé et pourquoi cela aide, afin que vous puissiez comprendre les mises à jour grâce à un modèle mental précis.
Pourquoi écrire directement dans le DOM devient coûteux
Au préalable de React, les mises à jour de l’interface étaient impératives : trouver un nœud et le modifier.
document.getElementById("title").innerText = "Hello";
Cela fonctionne bien pour une petite page. Lorsque des centaines ou des milliers d’éléments changent fréquemment, cela devient à la fois lent et difficile à gérer, car un changement dans le DOM peut forcer le navigateur à refaire :
- le calcul des styles et du layout
- le réajustement du contenu environnant
Chaque fois, le navigateur recalcule l’emplacement des éléments, leur taille et quels pixels redessiner. Ce travail est bien plus coûteux que la création ou la comparaison d’objets JavaScript. De plus, de nombreux morceaux de code qui interagissent indépendamment avec le DOM rendent facile le décalage entre l’écran et l’état de l’application.
Qu’est-ce que le Virtual DOM, en réalité ?
Le vrai DOM
Le vrai DOM est l’arbre de nœuds en temps réel que le navigateur construit à partir du markup, un nœud par élément. Même ceci :
<body>
<h1>Hello</h1>
</body>
devient un arbre interne lié au rendu et à la peinture de l’écran, et sa modification fréquente est ce qui déclenche le travail coûteux mentionné ci-dessus.
La représentation virtuelle
Le DOM virtuel est souvent considéré comme une copie légère du vrai DOM. Plus précisément, il s’agit d’une description de l’apparence que doit avoir l’interface utilisateur : des objets simples que vos composants renvoient lorsqu’ils s’affichent. React met d’abord à jour cette description avant d’intervenir sur le navigateur. Un élément ressemble approximativement à ceci :
{
type: "h1",
props: {
children: "Hello"
}
}
Ces objets sont faciles à créer et à comparer, ce qui permet à React de déterminer ce qui a changé avant d’effectuer toute opération réelle sur le DOM. JSX n’est qu’une syntaxe permettant de les générer.
De la première affichage à un arbre modifié
Lors du premier affichage d’un composant de ce type :
function App() {
return <h1>Hello World</h1>;
}
React construit l’arbre virtuel, crée des nœuds DOM correspondants et les insère dans la page. Les deux arbres sont désormais identiques, et l’interface utilisateur devient visible.
Plus tard, un gestionnaire de clic pourrait mettre à jour l’état :
setCount(count + 1);
ou lorsque un parent transmet de nouvelles propriétés. Cela indique qu’une partie de l’interface utilisateur peut nécessiter des modifications. React ne met pas à jour le DOM immédiatement ; il planifie un nouveau rendu, et les mises à jour provenant du même événement sont généralement regroupées.
Lors de ce rendu, React appelle à nouveau le composant et obtient un arbre mis à jour, de sorte qu’il contient désormais la version précédente ainsi que la nouvelle. L’ancien arbre :
<h1>Hello</h1>
Le nouvel arbre :
<h1>Hello Omer</h1>
La tâche consiste à déterminer précisément ce qui a changé.
Reconciliation : comment fonctionne la comparaison
La reconciliation signifie comparer l’arbre virtuel précédent avec le nouvel arbre ; cette comparaison est généralement appelée diffing. Pour chaque position, React vérifie si un élément a changé, est resté identique, ou a été ajouté ou supprimé. Conceptuellement :
Old Tree VS New Tree
L’objectif est d’appliquer l’ensemble le plus réduit de modifications possible pour transformer l’interface utilisateur ancienne en une nouvelle. Une comparaison d’arbres complètement générale serait trop lente, c’est pourquoi React utilise deux heuristiques. Si le type d’un élément change, par exemple de div en span, React remplace cet arbre sous-jacent plutôt que de comparer ses enfants. Dans les listes, il compare les enfants en se basant sur la key, d’où l’importance des clés stables : elles indiquent à React qu’un élément a été déplacé plutôt que remplacé.
Lorsque seul le texte change
Auparavant :
<h1>Hello</h1>
Après :
<h1>Hello Omer</h1>
<h1> conserve le même type à la même position ; seul son texte diffère. React garde donc le nœud DOM existant et met à jour uniquement le nœud de texte au lieu de recréer l’élément. Éviter toute opération qui n’est pas strictement nécessaire constitue le cœur de cette optimisation.
La phase d’application : ne modifier que ce qui a changé
Après avoir généré la différence, React écrit les modifications résultantes dans le DOM réel :
- mettre à jour du texte
- ajuster ou supprimer des attributs
- insérer de nouveaux éléments
- supprimer les éléments qui ont disparu
C’est la phase d’application, le seul moment où React interagit avec le DOM, et il ne modifie que ce que la différence a identifié. Le navigateur répeint ensuite les zones affectées. Pour en savoir plus sur le parcours allant de l’application aux pixels, consultez notre guide sur le rendu de React, des mises à jour d’état aux pixels à l’écran.
D’où provient l’amélioration des performances
Cette amélioration provient d’un nombre réduit d’opérations coûteuses sur le DOM. Au lieu de reconstruire tout le contenu, React compare les descriptions anciennes et nouvelles, calcule les différences minimales et ne modifie que les nœuds concernés. Comme la comparaison d’objets est bien moins coûteuse que la mutation du DOM, cela s’avère généralement avantageux dans les applications volumineuses.
Deux réserves permettent de rester réaliste quant à ce modèle. Le Virtual DOM n’est pas intrinsèquement plus rapide qu’un code DOM soigneusement optimisé ; sa valeur réside dans le fait de permettre d’écrire des interfaces utilisateur déclaratives tout en obtenant des mises à jour efficaces. De plus, le rendu n’est pas gratuit : React appelle toujours vos composants et compare leurs sorties, donc éviter les mises à jour inutiles reste important.
Points clés
- Le Virtual DOM est un ensemble d’objets simples décrivant l’interface utilisateur souhaitée, recréé à chaque rendu.
key comme raccourcis.