ブラウザに何かを表示する方法は1つではない。React・Svelte・Three.js・Flutter Webはそれぞれ異なる方法で画面を描いている。その違いを整理する。
ブラウザが画面を描く3つの手段
| 手段 | 概要 |
|---|---|
| DOM | HTMLタグをツリー構造で管理し、CSSでスタイルを当てる |
| Canvas | <canvas> 要素にJavaScriptから直接ピクセルを描く |
| WebAssembly | C++などをブラウザで動かし、Canvasに描画する |
フロントエンドフレームワークは、この3つのどれか(または組み合わせ)を使っている。
① DOM方式 — React・Svelte・Vue
仕組み
コンポーネント(JSX / .svelte)
↓
JavaScript が DOM ツリーを操作
↓
ブラウザのレンダリングエンジンが CSS を適用して描画
HTMLの <div>・<p>・<button> などの要素がDOMツリーとして存在し、CSSがスタイルを決める。開発者ツールで「要素を検証」すると中身が見える。
Virtual DOM(React)とコンパイラ方式(Svelte)
React はVirtual DOMという仮想のDOMツリーをメモリ上に持ち、差分だけ実際のDOMに反映する。
状態が変わる
↓
新しい Virtual DOM を作る
↓
前回との差分を計算(Diffing)
↓
差分だけ実際の DOM を更新
Svelte はコンパイル時にどのDOMを更新すべきか解析し、Virtual DOMを持たない直接更新のコードを生成する。
状態が変わる
↓
コンパイル済みのコードが直接 DOM を更新
(差分計算のランタイムコストがない)
DOM方式の特徴
- SEO・アクセシビリティが自然に機能する(HTMLが存在するため)
- ブラウザのテキスト選択・検索が使える
- CSSやブラウザ拡張機能との相性が良い
- 複雑なアニメーションや大量の描画更新は苦手
② Canvas方式 — Three.js・ゲームエンジン系
仕組み
JavaScript の描画命令
↓
<canvas> 要素の 2D/WebGL コンテキストに描画
↓
ピクセル単位で画面に出力
DOMに要素は存在しない。<canvas> が1枚あるだけで、その中身はJavaScriptが毎フレーム描き直す。
Three.jsはWebGL(GPU命令をブラウザから呼ぶAPI)を使った3D描画ライブラリ。60fpsで大量のポリゴンを描く用途に向いている。
Canvas方式の特徴
- アニメーション・3D・大量描画が得意
- SEOはできない(HTMLとしてコンテンツが存在しない)
- スクリーンリーダーが読めない
- ブラウザの「テキスト選択」「Ctrl+F検索」が使えない
③ WebAssembly + Canvas方式 — Flutter Web
仕組み
Dart で書いた Flutter アプリ
↓
Skia(C++の2D描画エンジン)を WebAssembly にコンパイル
↓
<canvas> 要素1枚に全 UI を描画
Flutter Webのデフォルトレンダラー(CanvasKit)は、C++製の描画エンジン「Skia」をWebAssemblyとして動かし、<canvas> 1枚に全UIを自前で描く。ブラウザのDOM・CSS・レイアウトエンジンを一切使わない。
なぜこの方式なのか
Flutter はもともとモバイルアプリ(iOS・Android)向けに設計されており、ネイティブUIウィジェットを使わず独自の描画エンジンで全UIを描く思想を持つ。Web版もその思想を引き継いでいる。
これにより、モバイルとWebでピクセル単位で完全に同じ見た目を実現できる。
Flutter Web の HTMLモード(補足)
Flutter Webには CanvasKit の他に HTMLレンダラーもある。こちらはDOMと <canvas> を組み合わせて描画するが、セマンティックなHTMLにはならない。パフォーマンスや見た目の一貫性を優先する場合は CanvasKit が使われる。
Flutter Web の特徴
| 項目 | 状況 |
|---|---|
| SEO | 困難(DOMにコンテンツがない) |
| アクセシビリティ | 制限あり(スクリーンリーダー非対応が基本) |
| テキスト選択・Ctrl+F | 動作しない or 制限あり |
| CSSでのカスタマイズ | できない |
| ピクセル完全一致 | モバイル・Web・デスクトップで同一 |
| 初回ロード | WASMのダウンロードが必要で重い |
3方式の比較
| React / Svelte | Three.js | Flutter Web(CanvasKit) | |
|---|---|---|---|
| 描画手段 | DOM + CSS | Canvas(WebGL) | Canvas(WASM + Skia) |
| HTMLの存在 | あり | なし | なし |
| SEO | 対応可 | 困難 | 困難 |
| アクセシビリティ | 対応可 | 困難 | 制限あり |
| CSSの適用 | できる | できない | できない |
| 得意な用途 | Webアプリ・コンテンツ | 3D・ビジュアライゼーション | クロスプラットフォームアプリ |
なぜ描画方式が違うのか
それぞれが解決したい問題が異なるから。
- React・Svelte → Webのドキュメント・UIを効率よく管理したい
- Three.js → 3DグラフィックスをWebで動かしたい
- Flutter → 1つのコードベースでモバイル・Web・デスクトップを同じ見た目で動かしたい
Webの標準(DOM・CSS)に乗ることは「ブラウザの資産(SEO・アクセシビリティ・テキスト処理)を使える」ことと引き換えに「ブラウザのレンダリングエンジンに従う」制約を受け入れることでもある。Flutter WebはWeb標準を捨てることで完全な描画の自由を手に入れた、という設計判断といえる。
まとめ
- DOM方式(React・Svelte)はHTMLとCSSを使い、SEO・アクセシビリティが自然に機能する
- Canvas方式(Three.js)はピクセル直接描画で3D・高頻度アニメーションが得意
- Flutter Web(CanvasKit)はWASMでC++の描画エンジンを動かし、DOM・CSSを一切使わない
- どの方式が「正しい」かではなく、何を作るかによって適切な方式が変わる