Reactの仮想DOMの概念がダーティモデルチェックよりもパフォーマンスが高いと言われているのはなぜですか?


372

私が見たリアクト(でのdevの話を- JSConf EU 2013再考ベストプラクティスを::リアクトピート・ハントを)とスピーカーは、モデルのダーティー・チェックが遅くなることが言及しました。しかし、仮想DOMは、ほとんどの場合、モデルよりも大きいはずなので、仮想DOM間の差分の計算は実際にはそれほど効率的ではありませんか?

私は本当に仮想DOMの潜在的な能力(特にサーバー側のレンダリング)が好きですが、すべての長所と短所を知りたいです。


この講演についても言及できると思います。youtube.com/ watch?v = -DX3vJiqxm4では、ベンチマークについて具体的に語っています。
inafalcao 2017

回答:


493

私はvirtual-domモジュールの主要な作成者なので、あなたの質問に答えられるかもしれません。実際にここで解決する必要がある2つの問題があります

  1. いつ再レンダリングしますか? 回答:データがダーティだと気づいたとき。
  2. どうすれば効率的に再レン​​ダリングできますか?回答:仮想DOMを使用して実際のDOMパッチを生成する

Reactでは、各コンポーネントに状態があります。この状態は、ノックアウトまたは他のMVVMスタイルのライブラリで見られる可能性があるオブザーバブルのようなものです。基本的に、React はこのデータがいつ変化するかを監視できるため、シーンをいつ再レンダリングするかを認識ています。ダーティチェックはオブザーバブルよりも低速です。定期的にデータをポーリングし、データ構造のすべての値を再帰的にチェックする必要があるためです。比較すると、状態に値を設定すると、一部の状態が変更されたことをリスナーに通知するため、Reactは状態の変更イベントをリッスンして、再レンダリングをキューに入れることができます。

仮想DOMは、DOMの効率的な再レンダリングに使用されます。これは、データのダーティーチェックとは実際には関係ありません。ダーティチェックの有無にかかわらず、仮想DOMを使用して再レンダリングできます。2つの仮想ツリー間のdiffの計算にはある程度のオーバーヘッドがありますが、仮想DOM diffは、データが変更されたかどうかではなく、DOMで何を更新する必要があるかを理解することです。実際、diffアルゴリズム自体はダーティチェッカーですが、代わりにDOMがダーティかどうかを確認するために使用されます。

状態が変化した場合にのみ、仮想ツリーを再レンダリングすることを目指しています。したがって、オブザーバブルを使用して状態が変化したかどうかを確認することは、不必要なツリーの差分が大量に発生する不要な再レンダリングを防止する効率的な方法です。何も変わっていなければ、何もしません。

仮想DOMを使用すると、シーン全体を再レンダリングする場合と同じようにコードを記述できます。背後で、DOMを更新して期待どおりの外観にするパッチ操作を計算する必要があります。したがって、仮想DOM diff / patchアルゴリズムはおそらく最適なソリューションはありませんが、アプリケーションを表現する非常に優れた方法を提供します。必要なものを正確に宣言するだけで、React / virtual-domがシーンをこのようにする方法を決定します。手動でDOMを操作したり、以前のDOMの状態について混乱したりする必要はありません。シーン全体を再レンダリングする必要もないため、パッチを適用するよりもはるかに効率が悪くなる可能性があります。


1
Reactはコンポーネントプロップのダーティーチェックを行いますか?setProps()関数がないのでお願いします。
bennlich 2014年


1
そのような例は何でしょうunnecessary re-rendersか?
vsync

9
「仮想DOM diff / patchアルゴリズムはおそらく最適なソリューションではないかもしれませんが」と言うとき、理論的にはより最適なソリューションを考えていますか?
CMCDragonkai 2015年

3
これは質問に答えるようには思えません。Reactでは、setStateを使用して状態が変化したことを通知する必要があります。実行できたthis.state.cats = 99としても、Angularが$ scopeツリーをダーティチェックするのと同じように、モデルの変更をチェックするためにダーティチェックが必要になります。これは2つの手法の速度の比較ではなく、バックボーンスタイルセッターを備えているため、Reactがダーティーチェックを行わないという単なる説明です。
スーパーミナミ

133

最近、Reactのdiffアルゴリズムに関する詳細な記事をここで読みました:http : //calendar.perfplanet.com/2013/diff/。私が理解していることから、Reactを速くするものは次のとおりです:

  • バッチDOM読み取り/書き込み操作。
  • サブツリーのみの効率的な更新。

ダーティチェックと比較した場合、IMOの主な違いは次のとおりです。

  1. モデルのダーティチェック:ReactコンポーネントはsetState、呼び出されるたびに明示的にダーティとして設定されるため、ここでは(データの)比較は必要ありません。ダーティチェックでは、(モデルの)比較は常に各ダイジェストループで行われます。

  2. DOMの更新:DOMを変更するとCSSスタイル、レイアウトも適用および計算されるため、DOMの操作は非常にコストがかかります。不要なDOMの変更による節約時間は、仮想DOMの比較に費やされる時間よりも長くなる可能性があります。

2番目のポイントは、フィールドの数が多いモデルやリストが大きいモデルなど、重要なモデルではさらに重要です。複雑なモデルの1つのフィールド変更により、ビュー/テンプレート全体ではなく、そのフィールドに関連するDOM要素に必要な操作のみが発生します。


1
実際、私はいくつかの記事も読んだので、(少なくとも一般的には)どのように機能するか、モデルのダーティチェックよりも効率的である理由を理解したかっただけです。そして1)はい、モデルを比較しませんが、はるかに大きな仮想DOMを比較します2)モデルのダーティチェックは、必要なものだけを更新する機能を提供します(Angularと同様)
Daniil

変更されたコンポーネントに対応する仮想DOMの一部のみを比較する必要があると思いますが、ダーティチェックは、何も変更されていなくても、すべてのスコープのすべての値に対してすべてのダイジェストループで発生します。大量のデータが変更された場合、仮想DOMの効率は低下しますが、小さなデータの変更には適していません。
2014年

1
Angularと言えば、ウォッチャーはダイジェスト中に状態を変更することもできるため、$scope.$digestはダイジェストサイクルごとに複数回実行されるため、部分的な仮想DOMツリー比較の1回だけの完全なデータ比較に対して複数回の実行になります。
2014年

4
多くの賢い開発者がブラウザ自体を修正してDOMの速度低下を一度にすべて解消することに私たちの注意を集中させるのではなく、「遅い」DOMなどに対処するためのトリックの「山」を発明しているのは残念です。それは、癌そのものを修復するだけでなく、人類のすべてのリソースを使って癌に対処し、患者の生活を改善する方法を研究するようなものです。くしゃみ。
vsync

@vsync DOMは画面に表示する必要があります。仮想DOMにはありません。いくつかの理想的なパフォーマンスのDOMがあっても、仮想DOMの作成はより高速になります。
ジェハン

75

私は本当に仮想DOMの潜在的な能力(特にサーバー側のレンダリング)が好きですが、すべての長所と短所を知りたいです。

-OP

ReactだけがDOM操作ライブラリではありません。詳細な説明とベンチマークを含むAuth0の記事を読んで、代替案を理解することをお勧めします。あなたが尋ねたように、私はここで彼らの長所と短所を強調します:

React.jsの仮想DOM

ここに画像の説明を入力してください

長所

  • 高速で効率的な「差分」アルゴリズム
  • 複数のフロントエンド(JSX、ハイパースクリプト)
  • モバイルデバイスで実行できるほど軽量
  • たくさんの牽引力とマインドシェア
  • Reactなしで(つまり、独立したエンジンとして)使用できます

短所

  • DOMの完全なメモリ内コピー(メモリ使用量が多い)
  • 静的要素と動的要素を区別しない

Ember.jsのグリマー

ここに画像の説明を入力してください

長所

  • 高速で効率的な差分アルゴリズム
  • 静的要素と動的要素の違い
  • EmberのAPIと100%互換性があります(既存のコードを大幅に更新しなくてもメリットがあります)
  • DOMの軽量のメモリ内表現

短所

  • エンバーでのみ使用されることを意味します
  • 利用可能なフロントエンドは1つのみ

インクリメンタルDOM

ここに画像の説明を入力してください

長所

  • メモリ使用量の削減
  • シンプルなAPI
  • 多くのフロントエンドおよびフレームワークと簡単に統合(最初からテンプレートエンジンバックエンドとして意味)

短所

  • 他のライブラリほど高速ではありません(これは議論の余地があります。以下のベンチマークを参照してください)
  • マインドシェアとコミュニティの使用が少ない

ReactJSのDOM操作の表現は、私にはほとんどずれていません。ReactJSの仮想DOMは、実際のDOMではなく、完全に変更されるものです-正しいですか?参照されている記事が参照している元の記事を見ていて、ここに表示されているのがteropa.info/images/onchange_vdom_change.svgです。 teropa.info/blog/2015/03/02/...
smile.al.d.way

35

ReactチームメンバーのSebastianMarkbågeからのコメントは次のとおりです。

Reactは、出力(これは既知のシリアライズ可能なフォーマット、DOM属性です)の差分を行います。つまり、ソースデータは任意の形式にすることができます。不変のデータ構造で、クロージャー内の状態にすることができます。

Angularモデルは参照透過性を保持しないため、本質的に変更可能です。既存のモデルを変更して、変更を追跡します。データソースが常に不変のデータまたは新しいデータ構造(JSON応答など)の場合はどうなりますか?

ダーティチェックとObject.observeは、クロージャスコープの状態では機能しません。

これら2つのことは、明らかに機能パターンを非常に制限しています。

さらに、モデルの複雑さが増すと、ダーティートラッキングを実行するのがますます高価になります。ただし、Reactのようにビジュアルツリーのみを比較すると、画面上に表示できるデータの量はUIによって制限されるため、それほど大きくなりません。上記のピートのリンクは、より多くのパフォーマンス上の利点をカバーしています。

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


2
実際、最後の段落について:間違っているはずです。モデルは仮想domよりも大きいので、各モデルの値には(ほとんどの場合)少なくとも1つの仮想dom要素(通常は複数)があります。表示されていないモデルが必要なのはなぜですか?
Daniil、2014年

2
キャッシュされたコレクションのページング。
ケンター2015

-2

Virtual Domは、reactによって発明されたのではありません。HTML domの一部です。軽量で、ブラウザ固有の実装の詳細から切り離されています。

仮想DOMは、Reactのローカルで単純化されたHTML DOMのコピーと考えることができます。これにより、Reactはこの抽象的な世界で計算を行い、「実際の」DOM操作をスキップできます。これは、多くの場合、ブラウザー固有の低速です。実際、DOMとVIRTUAL DOMの間に大きな違いはありません。

以下は、仮想Domが使用される理由です(ReactJSのソース仮想DOM)。

あなたがするとき:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. ブラウザはHTMLを解析する必要があります
  2. elementIdの子要素を削除します
  3. DOM値を新しい値で更新します
  4. 親と子のCSSを再計算します
  5. レイアウトを更新します。つまり、各要素は画面上の正確な座標です
  6. Render Treeをトラバースし、ブラウザのディスプレイにペイントします

CSSおよび変更されたレイアウトの再計算は複雑なアルゴリズムを使用し、パフォーマンスに影響を与えます。

同様にDOMプロパティを更新します。値。アルゴリズムに従います。

ここで、DOMを10回直接更新すると、上記のすべてのステップが1つずつ実行され、DOMアルゴリズムの更新にはDOM値の更新に時間がかかると想定します。

これが、Real DOMが仮想DOMよりも遅い理由です。


3
例について、domを直接または仮想domを介して変更している場合、最後に両方のケースでdomを変更します。
magallanes 2017年

はい、どちらの場合もdomを更新しますが、仮想domの場合は、キー(reactとは異なるアルゴリズムによって一意に定義される)フィールドまたは要素タグのみを更新します。一方、domを更新すると、dom全体が完全に更新または更新されます。
Hemant Nagarkoti 2017年

11
私はhackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130からこの記事を見ました。もしあなたが作者でないなら、たぶんソースを指摘する方が良いでしょう。
Jinggang

2
「これが、Real DOMが仮想DOMよりも遅い理由です。」いいえ、あなたはただ間違っています。
Roecrew、2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.