仮想DOM・リアルDOMとは?
ReactとjQueryのことを調べてたらリアルDOMって何?、仮想DOMって何?となったのでまとめてみました。
リアルDOM(DOM)とは?
DOMのモデルは文書を論理的なツリーで表現します。
文書の構造をメモリ内に表現することで、ウェブページとスクリプトやプログラミング言語を接続することができます。
ツリーのそれぞれの枝はノードで終わっており、それぞれのノードがオブジェクトを含んでいます。
DOMのメソッドでプログラム的にツリーにアクセスでき、これにより文書構造やスタイルやコンテンツを変更することができます。
ノードにはイベントハンドラーを割り当てることができ、イベントが発生するとイベントハンドラーが実行されます。
簡単にいうと
DOMとは、JavaScriptからHTMLドキュメントを操作するためのAPI(インターフェイス)
例題
以下のコードで例えると
<h1 id="title">Hello エンジニアHub</h1>
const title = document.getElementById('title'); title.innerHTML = '仮想DOM完全に理解した';
ここではDOMのgetElementByIdメソッドを用いて、HTMLドキュメントから#titleのIDを持つ要素を取得します。
さらにDOMのinnerHTMLプロパティにテキストを代入することで、HTMLドキュメントのh1#titleを書き換えることができます。
このように、DOMのおかげでJavaScriptからHTMLドキュメントを操作できます。
この他にもボタンクリック時のイベント登録や、スタイル・属性の変更、要素のサイズを取得といった処理も、全てDOMのAPIを使います。
この時のDOMを、仮想DOMと区別するため「リアルDOM」と呼ぶこともあります。
仮想DOMとレンダリングのコスト
先ほど書いたようにWebブラウザがDOMツリーを持っているのは、HTMLドキュメントをレンダリング(コンテンツをブラウザの画面に表示する処理)するためです。
リアルDOMを操作すると、その都度以下のような処理が実行されます。
1. DOMツリーを再構築する
2. DOMツリーとCSSOMツリー※を組み合わせてレンダリングツリーを構築する
3. レンダリングツリーでレイアウトを行い、各ノードの位置やスタイルを計算する
4. レイアウト結果をもとに描画する
※ CSSOM: CSS Object Modelの略で、CSS版DOMのようなものです。
レンダリングフローを見ると、レンダリングはブラウザにとってコストの高い処理になります。
レンダリングコストを減らす最も効果的な方法は、無駄なレンダリングをなくすことです。
そこで考えられたのが、仮想DOMという概念です。
仮想DOMは
ブラウザが持っていたDOMツリーを、JavaScriptのオブジェクト(仮想DOMツリー)として表現します。
そしてメモリ上の仮想DOMツリーを用いて差分検知を行い、必要最低限の差分のみをリアルDOMに反映するため、一般的にパフォーマンスが向上すると言われています。
最終的にはリアルDOMを操作しているため、DOMツリーの構造が大きくなればなるほど差分検知の計算量が増え、結果的に遅くなってしまうこともあります。
(おまけ) フレームワークで仮想DOMはどのように実装されているか
仮想DOMが実装されているフレームワークでは以下のような処理が行われます。
1. 仮想DOMツリーを2種類用意する(変更前後のツリー2種類)
2. 何らかのアクションでstate※が書き換わる
3. 仮想DOMを再構築する(更新された変更後の仮想DOMツリー)
4. 変更前後の2つの仮想DOMツリーを用いて差分検知する
5. 差分があった箇所だけリアルDOMに反映する
※ state: アプリケーションが保持している状態/データ。例えば、TODOアプリのタスクの完了状態など
参考資料
ドキュメントオブジェクトモデル (DOM) - Web API | MDN
仮想DOMってすげーんだぜ! - Qiita
仮想DOMは本当に“速い”のか? DOM操作の新しい考え方を、フレームワークを実装して理解しよう - エンジニアHub|若手Webエンジニアのキャリアを考える!