2026 年のフロントエンドパラダイム 12 種 — 自作言語のための調査ノート

VDOM、シグナル、コンパイル時リアクティビティ、Web Components、サーバー駆動、FRP、Islands、Resumability、状態機械、関数型 UI — 自分のプログラミング言語の WASM フロントエンド戦略を決めるために、2026 年のフロントエンドの実情を整理した。

frontendprogramming-languageswasmresearch

なぜこれを調べたのか

自作プログラミング言語を作っている。ML 系の小さな言語で、代数的エフェクト、capability passing、region ベースのメモリモデルを持っている。コアが固まったら WASM に出して、web UI も書けるようにしたい。

素朴な計画は「自作言語で React を再実装する」だ。ブログ記事としてはきれいな話だが、設計判断としては引っかかった。React は 2013 年の設計だ。それを定義した VDOM diff モデルは、もう何年もベンチマークで負け続けている。私が比較したいような言語 — JS の Solid、Rust の Leptos、OCaml の Bonsai — はとうの昔に先に進んでいる。

そこで腰を据えて、2026 年に人々が実際に web UI を何で作っているか、それぞれが何をトレードオフしているかをマップ化した。このノートはその調査結果である。自分のために書いたものでもあり、他の誰かにとっても役に立つかもしれない。

ひとつ前置きしておくと、私はバックエンド・言語側の人間でフロントエンドを眺めている立場である。これらのコミュニティのどれかを擁護できる立場にはない。それでも設計空間を把握することは私にとって重要で、なぜなら作っている言語が選択をしなければならないからだ — より正確には、複数の選択を順番にしていかなければならない。

12 のパラダイム

「React か Vue か」という二分法より、世界はずっと広い。何度か整理し直した結果、12 種類に収束した。境界は曖昧で、Vue 3 は #1 と #2 の中間にいるし、Svelte 5 は #3 から #2 に動いている。が、クラスタの中心は確かに存在する。

1. Virtual DOM + diff

代表: React、Vue 2、Preact、Inferno

「モダンフロントエンド」の元祖の物語。UI を state → vdom tree の純粋関数として表現する。state が変わるたびに全 tree を再生成し、前回の tree と diff を取って、差分だけを実 DOM に反映する。

メンタルモデルが単純である:UI を state の関数として考える。世界を再 render すれば、最小の DOM 変更をフレームワークが面倒見てくれる。長らくこれが支配的な教科書ストーリーで、React 以外のフレームワークも「props を取って JSX 風の出力を返すコンポーネント」を採用した。

代償は、毎回 tree を組み立ててから二つの tree を歩いて比較すること。画面を動かさない GC 圧と CPU 時間がそこで発生する。runtime も大きく、React + ReactDOM で minify 後 40KB 程度になる。

純粋な VDOM が最前線から退いたのは、それが壊れたからではない — アプリは普通に動いた。新しい設計が同じ仕事を少ない労力でこなすようになり、React 自身の現在の方向性(Server Components、Compiler)も、ある意味では 2013 年の前提から逃げるための試みである。

2. Fine-grained reactivity / シグナル

代表: Solid.js、Vue 3、Leptos (Rust)、Angular Signals、Preact Signals、Knockout(歴史的祖先)

「state が変わったら世界を作り直す」のではなく、それぞれの state をシグナル — 読める・書ける・購読できる値 — として持つ。render 関数の中でシグナルを読むと、その関数がそのシグナルに依存していることをフレームワークが記録する。シグナルが変わると、それを読んだ DOM ノードだけが更新される。

VDOM はない。コンポーネント単位の再 render もない。手動の useMemouseCallback も不要だ — 依存グラフは read を追跡することで自動的に組み立てられる。

これが 2026 年の JavaScript フレームワークベンチマークでほぼ全勝している。Krausest js-framework-benchmark で Solid が首位、Vue 3、Leptos、Angular Signals、Preact Signals、Svelte 5 が同じ方向に進んでいる。2020 年代中盤のフロントエンドを定義するトレンドがひとつあるとすれば、「みんなシグナルに移っている」これである。

トレードオフは概念的なものだ。シグナルはデフォルトで参照渡しになる。Solid の count は数値ではなく getter だ。JavaScript に見えるが JavaScript ではないコードは、React 初期の stale closure 問題と同じように人を躓かせる。

私の言語にとっては、これが最も興味深い target だ。capability passing は signal passing にほぼそのまま対応する。依存グラフはエフェクトを追跡できる型システムを求めていて、それは私が作っているものそのものだ。

3. Compile-time reactivity

代表: Svelte (1–4)、Marko

フレームワークが runtime をまったく出荷せず、代わりにコンパイラが普通の見た目のコードを精密な DOM 更新に変換する、という発想。

Svelte では let count = 0; count += 1 と書くと、コンパイラが DOM 更新呼び出しを emit してくれる。シグナル型もない、useState もない、proxy もない。出力 bundle は極小で、Svelte 3 はおよそ 3KB で出荷される。

代償は、コンパイラがブラックボックス化することだ。1 行のコードの挙動は、コンパイラがどう instrumentation するかに依存する。動けばよいが、動かないと困惑する。特にコンパイラが見えない動的なパターン — たとえばループ内で生成される state — で問題になる。

Svelte 5 は静かにこの戦いを一部譲歩して runes を導入した。シグナルそっくりの明示的な reactive primitive である。compile-time only という理想は中程度の複雑さを超えると押し通しづらかった。だが根底のアイデア — 「自分のコンパイラはフロントエンド最適化の機会である」 — は正しく、十分に活用されていない。

自前のコンパイラを持つ言語にとっては、これは興味深い領地だ。compile-time アプローチは、私の言語が元々やりたい macro / staged compilation 系の仕事と重なる。

4. Web Components + tagged template

代表: Lit、FAST、Stencil

ブラウザの実プリミティブを使う:Custom Elements、Shadow DOM、slot。小さなライブラリで包んで html\…`` テンプレートリテラルを与え、テンプレートを一度パースし、動的な穴だけを更新する。

謳い文句は「ブラウザが既にやっていることを再発明するのをやめよう」。Lit のコンポーネントは本物の HTMLElement だ。React からも Vue からも素の JS からも使える — フレームワークのプリミティブではなく、プラットフォームのプリミティブである。

このパラダイムは公開議論では目立たないが、エンタープライズでは重い存在だ。Apple、Google、Adobe、IBM はデザインシステムに Web Components を使っている。Lit の bundle size は小さく、複数スタックを横断して消費されるコンポーネントライブラリを出荷するなら「フレームワーク非依存」は真面目な機能になる。

弱点は、reactivity が浅いことだ。Lit は @property デコレータでフィールドを reactive にできるが、それは fine-grained reactivity というより「シュガー付きの命令的 DOM」に近い。小さな範囲なら問題ない。複雑な state graph になると、もっと欲しくなる。

5. Server-driven UI

代表: HTMX、Hotwire (Turbo + Stimulus)、Phoenix LiveView、Blazor Server、Inertia.js

client は dumb だ。HTML を render する。インタラクションごとにリクエストを送り、サーバーが HTML を返す — 全ページのこともあれば、hx-target のような属性で DOM にスワップされる断片のこともある。LiveView と Blazor Server は WebSocket を開き続けて、サーバーから部分更新をリアルタイムに push する。

ここ数年で変わったのは技術ではない — サーバー render の HTML は JavaScript より古い — そうではなく、多くのアプリにとってそれが正解だという認識が広まったことだ。HTMX は特に「フロントエンドの複雑さは選択の結果で、選ばないこともできる」というラリーポイントになった。ライブラリ本体は 14KB、残りは HTML と既存のバックエンドだけだ。

言語ビルダーにとって、これは群を抜いて簡単なフロントエンドストーリーだ:UI フレームワークを出荷する必要が実はない。サーバー側のよい言語とテンプレートストーリーを出荷すれば、残りは HTMX や LiveView 風の属性がやってくれる。インタラクションモデルは「リクエスト → HTML レスポンス → DOM スワップ」となり、言語はバックエンドの形のまま居続けることが許される。

代償は、すべてが往復になることだ。オフラインは効かない。楽観的 UI は難しい。CRUD 型の製品なら最高だが、ローカルに感じる必要のあるツール — ドローイングアプリ、IDE、リアルタイムゲーム — には合わない選択だ。

6. FRP (Functional Reactive Programming)

代表: Elm、Cycle.js、部分的近似としての RxJS

UI を時間に沿った値として扱う。イベントは stream になる。stream は mapfiltermergeswitch で合成できる。任意の瞬間の UI は、stream graph の現在状態の関数である。

これは reactivity の学術版だ。動けば美しく、動かないと残酷だ。Elm コミュニティはより制限された方言を磨き上げた — The Elm Architecture — 生の stream を明示的な Msg 型と update 関数に置き換えたもので、教えやすかった。

Elm と一部の PureScript / OCaml ライブラリの外では、純粋な FRP は市場を取れなかった。だがそのアイデアはあちこちにある:シグナルは本質的に FRP 文献の「behavior」だし、Solid の依存追跡モデルは 90 年代〜2000 年代の FRP 研究の直系子孫だ。

ML 系言語にとってはホームコート・アドバンテージだ。型システムが stream 合成を自然に扱い、エフェクトシステムが不純な部分をきれいに扱い、結果のコードは局所推論が証明可能なほど明確になる。問題は市場だ — 本番で FRP を書きたい人は非常に少なく、書きたい人は既に Elm を使っている。

7. 命令的 + ヘルパー

代表: jQuery、素の JS、Alpine.js

DOM ノードを掴んで、書き換える。イベントリスナーを繋ぐ。フレームワークを出荷しない。

これを「もう過去のもの」と分類したくなるが、実態はもっと曖昧だ。動いている本番コードの多く — 社内ツール、CMS 駆動のページ、Rails や Django アプリの上に乗っているもの — は今でも何らかの「ヘルパーライブラリ付き命令的 DOM」だ。Alpine.js は明示的に 2020 年代の jQuery として設計された:数 KB で、HTML に属性を散らせば reactivity が手に入る。

言語ビルダーにとって、命令的 + ヘルパーの道は自然な初期段階でもある。fine-grained reactivity はタダではない。最初に出荷できるのは「WASM モジュールが set_text 関数を export し、JS が DOM へ橋渡しする」だ。私の言語もそこから始まる。

8. Canvas / WebGL / WebGPU

代表: Figma、Pixi.js、three.js、Excalidraw、Google Maps と Earth の一部

DOM を完全に飛ばす。canvas を取って、ピクセルを描く。3D や重い 2D が必要なら、WebGL や WebGPU を使い GPU に仕事をさせる。

これは他のパラダイムと違うゲームだ。「フレームワーク」になろうとしているのではなく、自前の UI runtime を作っている。Figma のテキストレイアウト、選択、ヒットテスト、IME 処理 — それらは全部 canvas 上のカスタムコードだ。彼らがこうする理由は、DOM がボトルネックだからだ。Figma のスケールで「ブラウザに 100 万ノードのレイアウトをさせる」は無理で、「見える viewport を 60fps で自分で描く」が成立する。

WebAssembly はここに強い適合性がある。canvas ベースの道は、既存の C++ や Rust コードベースを移植するのに DOM ベースの道より遥かに親和的だからだ。Figma は周知のように、ブラウザに居る WASM C++ アプリケーションである。

私の言語にとっては、これは long tail の option だ。WASM が動いて言語が WebGL と話せるようになれば、ドローイングアプリ型の製品が成立する。だが汎用 web フレームワークへの道ではない — 特定の application class への道だ。

9. Islands Architecture

代表: Astro、Iles、Fresh (Deno)、Eleventy + Alpine

ページ全体を静的 HTML として出荷する。そしてインタラクティブにする必要のある小さな部分 — 検索ボックス、カートボタン、コメントフォーム — だけを個別に hydrate する。それぞれの「island」は独自のフレームワークインスタンスで動く。残りは素の HTML で、JS には触れられない。

ここ数年の大きなトレンドシフトのひとつだ。気づきは、コンテンツサイト — ブログ、ドキュメント、EC リスト — にとって SPA モデルは過剰だった、ということ。ページの大部分は変わらない。なぜそれに runtime を出荷する?

Astro はこれを具体化して出荷可能にし、モデルは広く模倣された。React Server Components は同じ本能のより踏み込んだ版だ:UI tree の大部分はインタラクティブである必要がない、ならクライアントでその料金を払わない。

言語ビルダーにとって、islands モデルは興味深い:「フレームワーク」を React の意味で作る必要がない。静的サイトジェネレーターと、小さなインタラクティブコンポーネントを埋め込む方法を作る。インタラクティブな部分は他のパラダイムどれを使ってもよい。

10. Resumable / Serializable (Qwik)

代表: Qwik

最前線だ。アプリ全体をサーバーで render する。HTML だけでなく JavaScript の state — クロージャのキャプチャ、イベントハンドラ — も HTML に直接シリアライズする。client は HTML をロードした瞬間にインタラクティブになる:hydration なし、JS 実行なし、「フレームワークをロード」もなし。何かをクリックしたときだけ、その特定のボタンのハンドラを lazy load する。

謳い文句は「アプリサイズに関係なく一定時間で interactive になる」。5MB の Qwik アプリは 50KB のそれと同じ速さで起動する。client は必要になるまで大部分を実行しないからだ。

実装は英雄的なコンパイラだ。Qwik はコードを何千もの小さなチャンクに刻み、それぞれを個別にフェッチ可能にする。すべてのクロージャはシリアライズ可能オブジェクトになる。必要なコンパイラ統合のレベルが高すぎて、今のところ Qwik は Qwik だけのものだ — 他のフレームワークはこの芸当を再現していない。

私の言語にとっては、これは最も野心的な target だ。私が握っているコンパイラ制御は resumability を試みるのに十分だ。だがエンジニアリングコストは大きく、観客は小さい。

11. State machine driven

代表: XState、Robot、Stately.ai

UI は有限状態機械だ。状態遷移は明示的に宣言される。view は現在状態から導出される。あり得ない状態は表現不能になる。

これが「フレームワーク」として現れることはまれだ。通常は React や Solid の上に乗る複雑な状態フロー管理のレイヤーだ — ウィザード、チェックアウト、動画プレイヤー UI、「ユーザーが実際に取り得る状態は何か」が「これは何に見えるか」より重要なあらゆる場所。

直和型とパターンマッチを持つ ML 言語にとって、状態機械はタダで落ちてくる。type State = Idle | Loading | Loaded of Data | Error of Reasonupdate : State → Msg → State は、ほぼ The Elm Architecture で、自然な fit だ。

12. Functional UI (ML 系)

代表: Elm、Halogen (PureScript)、Mint、Bonsai (OCaml、Jane Street 製)

The Elm Architecture を一般化したもの。Model がすべての state を持つ。view : Model → Html Msg がそれを render する。update : Msg → Model → Model が変更を扱う。副作用は update から返される値 (Cmd) として表現され、runtime が実行する。

これは ML コミュニティの UI への回答で、「原則的な版」と最も強く主張できる存在だ。Jane Street 内で重く使われている Bonsai は、OCaml で大規模・実用・社内ツール品質の UI を構築できることを実証している。Elm の「runtime exception ゼロ」の主張はマーケティングではない — 型システムが JavaScript を悩ませる種類のバグを丸ごと捕まえる、これは本当だ。

市場は小さい。Elm の開発ペースは落ち、PureScript はアカデミック寄りで、OCaml の web フロントエンドはほぼ Bonsai 型だ。だが私が作っているような言語にとって、これは自然な居場所に最も近い。私が凝ったことをせず Bonsai の設計を私の言語に移植するだけでも、もうそれで coherent で正当化可能なフロントエンドストーリーになっている。

最適化の 5 軸

12 のパラダイムがあって勝者がいない理由は、それぞれが違うものを最適化しているからだ。

  • Runtime 速度: シグナル (Solid、Leptos)、compile-time (Svelte)。state 変更ごとの仕事が少ないからベンチマークで勝つ。
  • Bundle size: compile-time (Svelte)、server-driven (HTMX)。出荷するコードが少ないから勝つ。
  • Time-to-interactive: resumability (Qwik)、islands (Astro)、server-driven。client が使えるようになる前に実行する量が少ないから勝つ。
  • 開発者体験: VDOM (React)、functional UI (Elm)。React はエコシステムの規模と採用しやすさで勝つ、Elm は内部一貫性とバグの少なさで勝つ。
  • 型安全 / 正しさ: functional UI (Elm、Bonsai)、FRP、状態機械。あり得ない状態が出荷前に消えているから勝つ。

ひとつの軸を制すればよいフレームワークだ。二つ制せば優れている。5 軸すべては誰も制していない — 目標が互いに戦うからだ。

2026 年に実際に動いているもの

上昇中: シグナル。言語を超え、フレームワークを超え。Angular が採用した。Vue は既にそこにいる。Svelte 5 は純 compile-time から退いてシグナル側に寄せた。Preact は持っている。React Compiler でさえ、シグナル前提で書かれていないコードに対してシグナル的なものを fake しようとしている。2026 年に新規プロジェクトのデフォルト reactivity モデルを選ぶなら、シグナルが明白な回答だ。

上昇中: 真面目な選択肢としての server-driven UI、レトロではなく。HTMX には本物の採用者が出てきた。Phoenix の LiveView は成熟した。Inertia は「Laravel 型のバックエンド」と「React 型のフロントエンド」を橋渡しした。多くのチームが、実際の製品に対して SPA モデルが過剰だったと認め始めている。

ゆっくり上昇: islands と resumability。両方ともツーリングの成熟度に縛られているが、根底の本能 — 「client がアプリ全部である必要はない」 — は広く正しい。

横ばいか衰退: 純 VDOM。React 自身が元の VDOM-only ストーリーから離れている。現在の方向は Server Components + Compiler で、2013 年版の React より「compile-time + server-driven」に近い。

ニッチだが安定: FRP、functional UI、状態機械。10 年間ずっとそこにある — 小さなコミュニティ、強い内部論理、ブレイクアウトの瞬間はない。

私の言語にとっての意味

私が作っているのは ML 系の言語で、エフェクトハンドラ、capability passing、region ベースのメモリ、小さな表面積を持つ。問題は、この 12 のパラダイムのうち私が説得力をもって支えられるのはどれで、最初にどれ向けに作るべきか、だ。

言語が既にできることに最もよく合うパラダイム:

  • Fine-grained reactivity (シグナル) — capability はシグナルだ。関数内でシグナルを読むことは、私の型システムが既に追跡しているエフェクトそのものだ。最も強い機械的 fit。
  • Functional UI (Elm / Bonsai) — 言語は既に ML 系だ。Bonsai 風のアーキテクチャは私の言語で OCaml を書く感覚になる。作るのも教えるのも安い。
  • 状態機械 — 直和型とパターンマッチがあるので、状態機械はタダで落ちてくる。「XState」を作る必要がない — 言語に既にプリミティブがある。
  • Compile-time reactivity (Svelte 風) — コンパイラを握っている。手間は多いが、最も「言語固有」の角度だ。

弱い fit のパラダイム:

  • VDOM — ゴミを生成し、私の region allocator と戦い、私の型システムの強みを使わない。追う価値なし。
  • 純 Canvas/WebGL UI — 成立するが、別の製品だ、フロントエンドフレームワークではない。
  • Resumability — 原理的には可能だが、当面は実装コストが利得を上回る。

実際にやりそうな順番:

  1. WASM target がブラウザでテキストを表示できる程度に安定化する。フレームワークなし。
  2. 命令的 + ヘルパー層 — wasm-bindgen 相当のバインディングで直接 DOM アクセス。カウンターアプリが動く。
  3. シグナル導入。これが最初の本物の設計判断。capability passing がシグナル購読にマップされる。Solid みたいになると予想する、ただしより型がついて。
  4. 宣言的 DOM 構築 — おそらく JSX より Lit に近い tagged template スタイル。compile-time テンプレートパースが欲しい。
  5. コンポーネント合成。ここで Bonsai の設計を改めて確認し、近く追従するか決める。
  6. つまらないが必要なもの:ルーティング、フォーム、フェッチ、ビルドツーリング。

これはおおよそ 6 ヶ月〜2 年の趣味プロジェクト規模だ。初期段階は記事として出せる程度に小さい。後段は、言語が実アプリで使う価値のある状態に至るかにかかっていて、それは別の、より難しい問いだ。

最後に

今日フロントエンドスタックを選んでいて、これを読んでいるなら、短い結論はこうだ:シグナルが今のデフォルトで、server-driven が人々が思うより正解な場面が多く、純 VDOM はもう賢い賭けではない。

自作言語を作っていてフロントエンドストーリーまで手を出すか迷っているなら — 出してよい、ただしまず言語をきちんと作り、言語が既に持っているプリミティブと噛み合うパラダイムを選ぶこと。言語の設計が違うのに React を移植する意味はない。

実装ステップは進捗に応じて別ノートで書く予定。

← Back to Notes