新人フロントエンドエンジニアが仮想 DOM について色々調べてみた
はじめに
ども、20卒の新人フロントエンドエンジニアのナッパ(@nappa_bebeji)です。
今回は Vue, Reactで使われている仮想 DOM について、書いていきたいと思います。
そもそも DOM ってなに ?
MDN web docs - DOMの紹介 - ではこう書かれています。
Document Object Model (DOM) は HTML や XML 文書のためのプログラミングインターフェイスです。ページを表現するため、プログラムが文書構造、スタイル、内容を変更することができます。 DOM は文書をノードとオブジェクトで表現します。そうやって、プログラミング言語をページに接続することができます。
ドキュメントオブジェクトモデル (DOM) は、その同じ文書を表現、保存、操作する方法です。DOM はウェブページの完全なオブジェクト指向の表現で、 JavaScript のようなスクリプト言語から変更できます。
簡単に言うと、JavaScript から HTML や XML を直接変更できるインターフェイスです。
仮想 DOM と区別して、リアル DOM と呼ばれることもあります。
DOM ツリーとは ?
WebブラウザはHTMLの書く要素をオブジェクトとして扱い、ツリー状にして管理しています。
このツリーを DOM ツリーといいます。またツリーの要素ひとつひとつを Node といいます。
仮想 DOM もリアル DOM もこのようなツリー状にして管理しています。
レンダリングの仕組み
Webブラウザが DOM ツリーを持っているのは、HTMLファイルをレンダリング(コンテンツを画面に表示するための処理)するためです。
リアル DOMを操作すると、次のサイクルで都度処理が行われます。
- DOM ツリーを再構築する
- DOM ツリー, CSSOM ツリー を組み合わせてレンダリングツリーを構築する
- レンダリングツリーのレイアウト処理を行い、各 Node の位置やスタイルを計算する
- レイアウト処理の結果を描画する
この通り、レンダリングはブラウザにとってコストの高い処理です。
仮想 DOM は無駄なレンダリング処理をなくし、レンダリングコストを減らします。
仮想 DOM の概念
仮想 DOM はブラウザが持っている DOM ツリーを JavaScript オブジェクトとして表現し、メモリ上にキャッシュされた仮想 DOM ツリーを用いて差分検知を行い、必要最低限の変更だけリアル DOM に反映します。
つまり、都度 DOM ツリーを再構築するわけではないので、無駄なレンダリングを無くし、レンダリングコストを減らすことができます。
ただ仮想 DOM ツリーの大きさが大きいほど、差分の計算量が増え、時間がかかってしまうというデメリットがあります。
ReactなどのJSフレームワークを使うとどうなの?
仮想 DOM は React, Vue などで使用されていますが、本当にレンダリングコストを減らすことができるのでしょうか?
以下のページでも書いてますが、フレームワークによって変わります。
- Reactが性能面で総合的に有利
- Angularは起動に不利だが、実行性能(フレームレート)は良好
- Vueは大量にコンポーネントを配置するような場面においては不利
このように、条件によってはレンダリングコストが高くなることもあります。
まとめ
- DOM は、JavaScript からHTMLを直接変更できるインターフェイス
- Web ブラウザは DOM ツリー を構築して、管理している
- 仮想 DOM は DOM ツリーを JavaScript オブジェクトとして表現し、メモリ上にキャッシュされた仮想 DOM ツリーの差分を検知し、必要最低限の変更だけリアル DOM に反映する
- JSフレームワーク次第では、レンダリングコストが減らせるわけではない
Discussion