😎

新人フロントエンドエンジニアが仮想 DOM について色々調べてみた

2020/10/05に公開

はじめに

ども、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を操作すると、次のサイクルで都度処理が行われます。

  1. DOM ツリーを再構築する
  2. DOM ツリー, CSSOM ツリー を組み合わせてレンダリングツリーを構築する
  3. レンダリングツリーのレイアウト処理を行い、各 Node の位置やスタイルを計算する
  4. レイアウト処理の結果を描画する


ブラウザのしくみ: 最新ウェブブラウザの内部構造より引用

この通り、レンダリングはブラウザにとってコストの高い処理です。
仮想 DOM は無駄なレンダリング処理をなくし、レンダリングコストを減らします。

仮想 DOM の概念

仮想 DOM はブラウザが持っている DOM ツリーを JavaScript オブジェクトとして表現し、メモリ上にキャッシュされた仮想 DOM ツリーを用いて差分検知を行い、必要最低限の変更だけリアル DOM に反映します。
つまり、都度 DOM ツリーを再構築するわけではないので、無駄なレンダリングを無くし、レンダリングコストを減らすことができます。

ただ仮想 DOM ツリーの大きさが大きいほど、差分の計算量が増え、時間がかかってしまうというデメリットがあります。

ReactなどのJSフレームワークを使うとどうなの?

仮想 DOM は React, Vue などで使用されていますが、本当にレンダリングコストを減らすことができるのでしょうか?
以下のページでも書いてますが、フレームワークによって変わります。

Vue・React・Angularのパフォーマンス比較検証

  • Reactが性能面で総合的に有利
  • Angularは起動に不利だが、実行性能(フレームレート)は良好
  • Vueは大量にコンポーネントを配置するような場面においては不利

このように、条件によってはレンダリングコストが高くなることもあります。

まとめ

  • DOM は、JavaScript からHTMLを直接変更できるインターフェイス
  • Web ブラウザは DOM ツリー を構築して、管理している
  • 仮想 DOM は DOM ツリーを JavaScript オブジェクトとして表現し、メモリ上にキャッシュされた仮想 DOM ツリーの差分を検知し、必要最低限の変更だけリアル DOM に反映する
  • JSフレームワーク次第では、レンダリングコストが減らせるわけではない

Discussion