Pourquoi le concept React de DOM virtuel est-il dit plus performant que la vérification de modèle sale?

372

J'ai vu une discussion sur le développement de React ( Pete Hunt: React: repenser les meilleures pratiques - JSConf EU 2013 ) et le conférencier a mentionné que la vérification du modèle peut être lente. Mais le calcul de la différence entre les DOM virtuels n'est-il pas encore moins performant puisque le DOM virtuel, dans la plupart des cas, devrait être plus grand que le modèle?

J'aime vraiment la puissance potentielle du Virtual DOM (en particulier le rendu côté serveur) mais j'aimerais connaître tous les avantages et les inconvénients.

Daniil
la source
Je pense que vous pourriez également mentionner cet exposé youtube.com/watch?v=-DX3vJiqxm4 où il parle spécifiquement de repères.
inafalcao

Réponses:

493

Je suis l'auteur principal d'un module de dom virtuel , donc je pourrais être en mesure de répondre à vos questions. Il y a en fait 2 problèmes qui doivent être résolus ici

  1. Quand dois-je effectuer un nouveau rendu? Réponse: Quand j'observe que les données sont sales.
  2. Comment effectuer un nouveau rendu efficace? Réponse: utiliser un DOM virtuel pour générer un vrai patch DOM

Dans React, chacun de vos composants a un état. Cet état est semblable à un observable que vous pourriez trouver dans les bibliothèques de style knockout ou MVVM. Essentiellement, React sait quand restituer la scène car il est capable d'observer quand ces données changent. La vérification incorrecte est plus lente que les observables, car vous devez interroger les données à intervalles réguliers et vérifier toutes les valeurs de la structure de données de manière récursive. Par comparaison, la définition d'une valeur sur l'état signalera à un auditeur qu'un certain état a changé, de sorte que React peut simplement écouter les événements de changement sur l'état et mettre en file d'attente un nouveau rendu.

Le DOM virtuel est utilisé pour un nouveau rendu efficace du DOM. Ce n'est pas vraiment lié à une vérification incorrecte de vos données. Vous pouvez effectuer un nouveau rendu à l'aide d'un DOM virtuel avec ou sans vérification incorrecte. Vous avez raison en ce qu'il y a des frais généraux dans le calcul du diff entre deux arborescences virtuelles, mais le diff DOM virtuel consiste à comprendre ce qui doit être mis à jour dans le DOM et non pas si vos données ont changé ou non. En fait, l'algorithme diff est un vérificateur sale lui-même mais il est utilisé pour voir si le DOM est sale à la place.

Nous visons à restituer l'arbre virtuel uniquement lorsque l'état change. Donc, utiliser un observable pour vérifier si l'état a changé est un moyen efficace d'empêcher les re-rendus inutiles, ce qui entraînerait beaucoup de différences d'arbre inutiles. Si rien n'a changé, nous ne faisons rien.

Un DOM virtuel est agréable car il nous permet d'écrire notre code comme si nous restituions la scène entière. Dans les coulisses, nous voulons calculer une opération de correctif qui met à jour le DOM pour voir comment nous nous attendons. Ainsi, alors que l'algorithme de diff / patch DOM virtuel n'est probablement pas la solution optimale , il nous donne un très bon moyen d'exprimer nos applications. Nous déclarons juste exactement ce que nous voulons et React / virtual-dom déterminera comment faire ressembler votre scène à ceci. Nous n'avons pas à faire de manipulation manuelle du DOM ni à être confus au sujet de l'état précédent du DOM. Nous n'avons pas non plus à restituer la scène entière, ce qui pourrait être beaucoup moins efficace que de la patcher.

Matt Esch
la source
1
React vérifie-t-il les accessoires des composants? Je demande parce qu'il n'y a pas de fonction setProps ().
bennlich
1
quel en serait un exemple unnecessary re-renders?
vsync
9
Lorsque vous dites "Alors, alors que l'algorithme de diff / patch DOM virtuel n'est probablement pas la solution optimale", avez-vous en tête une solution théoriquement plus optimale?
CMCDragonkai
3
Cela ne semble pas vraiment répondre à la question. React vous oblige à utiliser setState pour signaler que l'état a changé. Si vous this.state.cats = 99pouviez le faire, vous auriez toujours besoin d'une vérification sale pour vérifier le changement de modèle, tout comme Angular dirty vérifie l'arborescence $ scope. Ce n'est pas une comparaison de la vitesse des deux techniques, c'est simplement une déclaration que React ne fait pas de vérification sale car il a un setter de style Backbone à la place.
superluminaire
133

J'ai récemment lu un article détaillé sur l'algorithme de diff de React ici: http://calendar.perfplanet.com/2013/diff/ . D'après ce que je comprends, ce qui rend React rapide est:

  • Opérations de lecture / écriture DOM par lot.
  • Mise à jour efficace de la sous-arborescence uniquement.

Par rapport au dirty-check, les principales différences de l'OMI sont:

  1. Vérification des modèles : le composant React est explicitement défini comme sale à chaque setStateappel, il n'y a donc pas de comparaison (des données) nécessaire ici. Pour les vérifications incorrectes, la comparaison (des modèles) se produit toujours à chaque boucle de résumé.

  2. Mise à jour DOM : les opérations DOM sont très coûteuses car la modification du DOM va également appliquer et calculer les styles CSS, les mises en page. Le temps gagné par une modification DOM inutile peut être plus long que le temps passé à différer le DOM virtuel.

Le deuxième point est encore plus important pour les modèles non triviaux tels que ceux avec une énorme quantité de champs ou une grande liste. Un changement de champ d'un modèle complexe se traduira uniquement par les opérations nécessaires pour les éléments DOM impliquant ce champ, au lieu de l'ensemble de la vue / du modèle.

tungd
la source
1
En fait, j'ai lu quelques articles aussi, alors maintenant (au moins en général) comment cela fonctionne, je voulais juste comprendre pourquoi cela peut être plus efficace qu'une vérification sale du modèle. Et 1) Yup, il ne compare pas les modèles mais compare un dom virtuel beaucoup plus grand 2) Le sale contrôle du modèle nous permet de mettre à jour uniquement ce qui est nécessaire (comme le fait Angular)
Daniil
Je crois que seules les parties du DOM virtuel correspondant au composant modifié doivent être comparées, tandis que la vérification incorrecte se produit à chaque boucle de résumé, pour chaque valeur sur chaque étendue, même si rien n'a changé. Si une grande quantité de données changeait, alors Virtual DOM serait moins efficace, mais pas pour de petites modifications de données.
tungd
1
En parlant d'Angular, parce que les observateurs peuvent également muter l'état pendant le résumé, le $scope.$digestest exécuté plusieurs fois par cycle de résumé, il s'agit donc de plusieurs fois de comparaison complète des données par rapport à une seule fois de comparaison d'arborescence DOM virtuelle partielle.
tungd
4
il est triste que tant de développeurs intelligents inventent des "montagnes" de trucs pour gérer les DOM "lents" et ainsi de suite, au lieu de concentrer notre attention combinée pour simplement réparer les navigateurs eux-mêmes et nous débarrasser de la lenteur des DOM une fois pour toutes. c'est comme utiliser toutes les ressources de l'humanité pour rechercher des moyens de lutter contre le cancer et d'améliorer la vie d'un patient, au lieu de simplement réparer le cancer lui-même. Ridicules.
vsync
@vsync Le DOM doit afficher des éléments à l'écran. Un DOM virtuel ne le fait pas. Même avec un DOM performant idéal, la création d'un DOM virtuel sera plus rapide.
Jehan
75

J'aime vraiment la puissance potentielle du Virtual DOM (en particulier le rendu côté serveur) mais j'aimerais connaître tous les avantages et les inconvénients.

- OP

React n'est pas la seule bibliothèque de manipulation DOM. Je vous encourage à comprendre les alternatives en lisant cet article d'Auth0 qui comprend des explications détaillées et des références. Je vais souligner ici leurs avantages et leurs inconvénients, comme vous l'avez demandé:

DOM virtuel de React.js

entrez la description de l'image ici

AVANTAGES

  • Algorithme de "diffing" rapide et efficace
  • Frontends multiples (JSX, hyperscript)
  • Assez léger pour fonctionner sur les appareils mobiles
  • Beaucoup de traction et de partage de l'esprit
  • Peut être utilisé sans React (c'est-à-dire comme moteur indépendant)

LES INCONVÉNIENTS

  • Copie complète en mémoire du DOM (utilisation de la mémoire plus élevée)
  • Pas de différenciation entre les éléments statiques et dynamiques

Ember.js 'Glimmer

entrez la description de l'image ici

AVANTAGES

  • Algorithme de différenciation rapide et efficace
  • Différenciation entre les éléments statiques et dynamiques
  • 100% compatible avec l'API d'Ember (vous obtenez les avantages sans mises à jour majeures de votre code existant)
  • Représentation légère en mémoire du DOM

LES INCONVÉNIENTS

  • Destiné à être utilisé uniquement dans Ember
  • Une seule interface disponible

DOM incrémentiel

entrez la description de l'image ici

AVANTAGES

  • Utilisation réduite de la mémoire
  • API simple
  • S'intègre facilement à de nombreux frontends et frameworks (comme un backend de moteur de modèle depuis le début)

LES INCONVÉNIENTS

  • Pas aussi rapide que les autres bibliothèques (c'est discutable, voir les benchmarks ci-dessous)
  • Moins de partage d'esprit et d'utilisation communautaire
falsarella
la source
La représentation de la manipulation DOM de ReactJS me semble peu éloignée. Le DOM virtuel du ReactJS est celui qui change entièrement, pas le DOM réel - correct? Je regarde l'article d'origine, les références des articles référencés et voici ce que je vois - teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way
35

Voici un commentaire du membre de l'équipe React, Sebastian Markbåge, qui met en lumière:

React fait la différence sur la sortie (qui est un format sérialisable connu, les attributs DOM). Cela signifie que les données source peuvent être de n'importe quel format. Il peut s'agir de structures de données immuables et de l'état à l'intérieur des fermetures.

Le modèle angulaire ne préserve pas la transparence référentielle et est donc intrinsèquement mutable. Vous modifiez le modèle existant pour suivre les modifications. Que faire si votre source de données est à chaque fois des données immuables ou une nouvelle structure de données (telle qu'une réponse JSON)?

La vérification sale et Object.observe ne fonctionnent pas sur l'état de la portée de fermeture.

Ces deux choses limitent évidemment les schémas fonctionnels.

De plus, lorsque la complexité de votre modèle augmente, il devient de plus en plus coûteux de faire un suivi sale. Cependant, si vous ne différez que dans l'arborescence visuelle, comme React, cela n'augmente pas autant car la quantité de données que vous pouvez afficher à l'écran à un moment donné est limitée par les interfaces utilisateur. Le lien de Pete ci-dessus couvre plus des avantages de perf.

https://news.ycombinator.com/item?id=6937668

Sophie Alpert
la source
2
En fait, à propos du dernier paragraphe: cela devrait être faux: le modèle est plus grand que le dom virtuel car pour chaque valeur de modèle, il y a (dans la plupart des cas) au moins un élément dom virtuel (et généralement beaucoup plus qu'un). Pourquoi est-ce que je veux un modèle qui n'est pas montré?
Daniil
2
Paginer les collections mises en cache.
kentor
-2

Virtual Dom n'est pas inventé par react. Il fait partie de HTML dom. Il est léger et détaché des détails d'implémentation spécifiques au navigateur.

Nous pouvons considérer le DOM virtuel comme une copie locale et simplifiée de React du DOM HTML. Il permet à React de faire ses calculs dans ce monde abstrait et d'ignorer les «vraies» opérations DOM, souvent lentes et spécifiques au navigateur. En fait, il n'y a pas de grande différence entre DOM et VIRTUAL DOM.

Voici les points pourquoi Virtual Dom est utilisé (source Virtual DOM dans ReactJS ):

Quand vous faites:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. Le navigateur doit analyser le code HTML
  2. Il supprime l'élément enfant de elementId
  3. Met à jour la valeur DOM avec une nouvelle valeur
  4. Recalculez le CSS pour le parent et l'enfant
  5. Mettre à jour la disposition, c'est-à-dire que chaque élément coordonne exactement à l'écran
  6. Parcourez l'arbre de rendu et peignez-le sur l'écran du navigateur

Le recalcul du CSS et des mises en page modifiées utilise un algorithme complexe et affecte les performances.

Ainsi que la mise à jour des propriétés DOM ie. valeurs. Il suit un algorithme.

Supposons maintenant que si vous mettez à jour DOM 10 fois directement, toutes les étapes ci-dessus seront exécutées une par une et la mise à jour des algorithmes DOM prendra du temps pour mettre à jour les valeurs DOM.

C'est pourquoi le Real DOM est plus lent que le DOM virtuel.

Hemant Nagarkoti
la source
3
À propos de l'exemple, si vous modifiez le dom directement ou via un dom virtuel, enfin pour les deux cas, vous changez le dom.
magallanes
Oui, dans les deux cas, nous mettons à jour dom, mais dans le cas de dom virtuel, il met à jour uniquement cette clé (définie de manière unique par l'algorithme différent de react) ou la balise d'élément. Alors que la mise à jour du dom met à jour ou rafraîchit le dom entièrement.
Hemant Nagarkoti
11
J'ai vu cet article sur hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 . Il vaut peut-être mieux indiquer la source si vous n'êtes pas l'auteur.
Jinggang
2
"C'est pourquoi le Real DOM est plus lent que le DOM virtuel." Non monsieur, vous vous trompez.
Roecrew