Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
フロントエンドUIフレームワークのこれまでとこれから
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
TOMIKAWA Sotaro
September 11, 2026
Programming
280
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
フロントエンドUIフレームワークのこれまでとこれから
https://frontend-conf.fukuoka.jp/2026/speakers/tomikawa-sotaro?hl=ja
TOMIKAWA Sotaro
September 11, 2026
More Decks by TOMIKAWA Sotaro
See All by TOMIKAWA Sotaro
ReactとSvelteのその先、Ripple-TS / Beyond React and Svelte: Ripple-TS
ssssota
3
2.6k
Atomics APIを知る / Understanding Atomics API
ssssota
2
1.4k
なんでRustの環境構築してないのにRust製のツールが動くの? / Why Do Rust-Based Tools Run Without a Rust Environment?
ssssota
15
56k
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
3.3k
漸進。
ssssota
0
3.7k
Preact、HooksとSignalsの両立 / Preact: Harmonizing Hooks and Signals
ssssota
1
3.8k
useSyncExternalStoreを使いまくる
ssssota
6
7k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
8
6.3k
新しいAPI createRawSnippet触ってみた / What is the createRawSnippet?
ssssota
2
350
Other Decks in Programming
See All in Programming
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
140
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
150
Hello, Hiroshima Geospatial Data! — Exploring DoboX with Python
ra0kley
0
180
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
340
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
110
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
3
520
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.5k
Pythonの実行はどこまで賢くなったのか? CPythonとPyPyから見る最適化のしくみ
curekoshimizu
4
2.8k
typoなんかねぇよ
raspython3
0
670
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
160
Go を使い始めて 2 ヶ月の学び / My first two months with Go
contour_gara
0
420
ソフトウェアラスタライザ
fadis
1
790
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
680
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
340
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
The Limits of Empathy - UXLibs8
cassininazir
1
640
The Pragmatic Product Professional
lauravandoore
37
7.4k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Optimizing for Happiness
mojombo
378
71k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
440
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
490
Paper Plane
katiecoart
PRO
2
53k
Transcript
フロントエンドUIフレームワークの これまでとこれから ssssota #fec_fukuoka
Hi there 👋 TOMIKAWA Sotaro / ssssota 仕事はReact、趣味はSvelte/Preact フロントエンドフレームワークぜんぶすき ⼤学の2年間だけ福岡に住んでいました
フロントエンドUIフレームワーク
React Svelte フロントエンドUIフレームワーク SolidJS Preact Vue.js Angular
フロントエンドUIフレームワーク → 今回はWebを第⼀のプラットフォームとする宣⾔的UIを記述するための ライブラリ・フレームワークを指す
の、これまでとこれから
歴史を順に追っていく
HTML(1990年代前半〜) HTMLは、広義の宣⾔的UIである。 ⽂書構造をマークアップするもの。
動的なWeb(1995年ごろ〜) JavaScriptの登場、HTMLを操作できるように。 Java Applet, Flash, Silverlightでリッチな表現も登場。
Ajax(2005年ごろ〜) Asynchronous JavaScript and XML. ⾮同期で情報を取得して、画⾯を更新するように。
jQuery(2006年ごろ〜) jQueryでDOM操作やAjaxが容易に... 操作と更新が増え続け... コードは複雑に...
命令的UI
// 命令的UI let count = 0; const result = document.getElementById('result');
const doubleResult = document.getElementById('double-result'); const button = document.getElementById('increment'); button.addEventListener('click', () => { count++; result.textContent = count; doubleResult.textContent = count * 2; });
Model - View の分離 Backbone.js(2010年ごろ〜)など、 Model - Viewを分離するアプローチもあったが 描画は開発者が管理する必要があり苦しい。
宣⾔的UI
Knockout
Knockout(2012年ごろ〜) テンプレートとObservablesを使ったライブラリ。 `data-bind` 属性をHTMLに⼊れて表現する。
<div> <p data-bind="text: count"></p> <button data-bind="click: increment">+1</button> </div> <script> const
count = ko.observable(0); function increment() { count(count() + 1); } ko.applyBindings({ count, increment }); </script>
現代に⾄る宣⾔的UIの祖? HTMLとは異なり、 JavaScriptから値を取得し、表⽰ 値の変化に応じて、使⽤箇所を更新する
AngularJS, React, Vue.js, ...
React → 仮想DOM
仮想DOM React(2013年ごろ〜) 状態が変化したら、仮想のDOMツリーを構築、 現在の状態と⽐較することで変化した箇所を特定、更新
仮想のDOMツリー
再レンダー(この時点で画⾯は変わらない)
⽐較(reconciler)
実DOM適⽤(commit)
オブジェクト指向とコンポーネント
class でコンポーネントを定義する コンポーネントの状態、振る舞い、表⽰をまとめて定義する 形式が主流に。 状態はプロパティ、振る舞いはメソッドなど クラスインスタンスをUIコンポーネントとするのは ⼀定理にかなっていた。
class Counter extends React.Component { constructor(props) { super(props); this.state =
{ count: 0 }; } increment() { this.setState(state => ({ count: state.count + 1 })); } render() { return <div> <p>{this.state.count}</p> <button onClick={this.increment.bind(this)}>+1</button> </div>; } }
Vue.js Vue.js 0.X、1.0はKnockout的に使⽤箇所を追跡する。 Vue.js 2.Xは仮想DOMを使うように。
<template> <div> <p>{{ count }}</p> <button @click="increment">+1</button> </div> </template> <script>
export default { data() { return { count: 0 }; }, methods: { increment() { this.count++; } } }; </script>
ロジックの分離 クラスやオブジェクトではstateやライフサイクルに紐づくロ ジックの再利⽤が困難だった。
React Hooks
関数コンポーネントへ `useState` を使って状態を表現できるようになり、 ライフサイクルフック等外部接続は `useEffect` になった。 Hook単体でロジックを持ち、テスト可能、共有可能に。
function useCounter() { const [count, setCount] = useState(0); const increment
= () => setCount(c => c + 1); return { count, increment }; } function Counter() { const { count, increment } = useCounter(); return <div> <p>{count}</p> <button onClick={increment}>+1</button> </div>; }
Vue.js Composition API Reactに追従するようにVue 3 (Composition API)が公開 ロジックとデータを集約して関数を定義できる形式。 旧来のOptions APIに親しんでいたユーザーからの反発は
ありつつも、現在では受け⼊れられている。
<template> <div> <p>{{ count }}</p> <button @click="increment">+1</button> </div> </template> <script>
<script> export default { export default { data() { setup() { return { count: 0 }; const count = ref(0); }, const increment = () => { methods: { count.value++; increment() { }; this.count++; return { count, increment }; } } } }; }; </script> </script>
Signals の普及
SolidJSの登場 Signalsをベースに、JSXで記述できる 細粒度リアクティビティなフレームワーク。 「Reactのような関数コンポーネントで⾼パフォーマンス」 といった⾔説とともに登場。
Signals 値が格納された箱。 使われている箇所(=依存)が追跡できる。 依存を有向グラフで管理。
Fine-grained Reactivity ⽇本語で細粒度リアクティビティ。 Signalsを⽤いることで、利⽤箇所を追跡可能に。 Signalの値が変化した際に、利⽤箇所のみを更新する。
export function Counter() { const [count, setCount] = createSignal(0); const
increment = () => setCount(c => c + 1); return <div> <p>{count()}</p> <button onClick={increment}>+1</button> </div>; }
signalを元に実DOMが作られる
signalが変化する
signalを元に直接書き換える
Svelte 5, Vue Vapor
細粒度リアクティビティへの移⾏ 独⾃のコンパイル時最適化を⾏っていたSvelteは Svelte 5でSignalsベースの細粒度リアクティビティへ。 Vue.jsもVapor modeを開発。
<script> let count = $state(0); function increment() { count =
count + 1; } </script> <div> <p>{count}</p> <button onclick={increment}>+1</button> </div>
似たような話を 🤔
Knockout was right all along. Knockoutは最初から正しかった。 Svelte 5のRunesを紹介する記事の⼀節。 細粒度リアクティビティはSolidJSが原点ではなく、 Knockoutが原点に近い。
Vue Vaporも仮想DOMがなかったVue 1な仕組みに近い。
なぜ現代に帰ってきたのか そもそも仮想DOMが流⾏ったのは、テンプレートではなく JavaScriptとして扱いやすい形で、SSRや他プラットフォー ムへの活⽤などを⾒据えていたため。 そこから細粒度リアクティビティに帰ってきたのは、 JavaScriptのコンパイル技術や最適化が進歩し、 Knockoutの課題感を現代的な基準でクリアできたため。
ここまで歴史
UIフレームワークをいろんな⾯から⾒る
UIフレームワークの記述⽅法
JSX (TSX) いまのフロントエンド開発者で知らぬものはいない。 TypeScriptやそれ以外のツールチェインも標準サポートする 数少ないECMAScript拡張構⽂。 <p>Hello</p> は、 jsx("p", {children: "Hello"})
などと解釈できる。
テンプレート (SFC) HTML⾵DSL。 `<script>` や `<style>` タグを利⽤し、装飾も可能。 変換を前提とするので、JavaScriptで表現しづらいことも テンプレートは表現しやすい。 (双⽅向バインディングなど)
JSX vs. テンプレート JSX→独⾃の記法を覚える必要が少ない。⽐較的ただのJS 各ツールチェインのサポートを受けやすい。 テンプレート→ UI特化の構⽂で簡潔に記述できる。 細粒度リアクティビティと相性がいい。 ツールチェインのサポートは受けづらい。
細粒度リアクティビティ と JSX
関数コンポーネントは⼀度だけ実⾏する 細粒度リアクティビティなフレームワークでは、 ⼀般的に関数コンポーネントは初回しか実⾏されない。 ⼀度の実⾏で、コンポーネントの全貌を伝える。 状態変化毎に実⾏されるReactなどに慣れていると違和感。
SolidJS JSXを記述し細粒度リアクティビティを実現する。 JSXをコンパイルすることで最適化が⾏われる。 コンポーネント内で早期リターンができないなど、 記法への制約が強い。 分岐や反復のために、`<Show>`や`<For>`がある。
export function Counter() { const [count, setCount] = createSignal(0); const
increment = () => setCount(c => c + 1); const reset = () => setCount(0); return <Show when={count() > 0} fallback={<button onClick={increment}>Start</button>} > <p>{count()}</p> <button onClick={increment}>+1</button> <button onClick={reset}>Reset</button> </Show>; }
Preact @preact/signals というパッケージを使ってSignalsが 導⼊できる。これにも`<Show>`や`<For>`がある。 Preact⾃体は軽量な仮想DOMベースのライブラリなので、 早期リターンを使うと、従来の差分検出で更新される。
Vue JSX Vapor Vue.jsには細粒度リアクティビティを⽤いるVapor modeが ある。JSXも、それらを合わせたVue JSX Vaporもある。 例に漏れず早期リターンができない。 `v-if`や`v-for`といったディレクティブがある。
function Counter() { const count = ref(0); const increment =
() => { count.value += 1; }; const reset = () => { count.value = 0; }; } return ( <> <template v-if={count.value > 0}> <p>{count.value}</p> <button v-on={{click: increment}}>+1</button> <button v-on={{click: reset}}>Reset</button> </template> <button v-else v-on={{click: increment}}>Start</button> </> );
テンプレートと細粒度リアクティビティ テンプレートの場合は早期リターンという概念⾃体が 存在しないため、概念上の整合性が取りやすい。 Vue.jsやSvelteは独⾃の記法を覚える必要はあれど、その実 細粒度リアクティビティと相性は悪くない。
<script> let count = $state(0); const increment = () =>
{ count += 1; }; const reset = () => { count = 0; }; </script> {#if count > 0} <p>{count}</p> <button onclick={increment}>+1</button> <button onclick={reset}>Reset</button> {:else} <button onclick={increment}>Start</button> {/if}
テンプレートとTypeScript
TypeScriptのサポートを受けるために TypeScriptはJSXしかサポートしていないので、 Vue.js、Svelteなどは独⾃のサポートが必要。 LSPをラップしたCLI、IDE拡張をそれぞれ提供している。 • vue-tsc • svelte-check
TypeScriptの進化
TypeScript Content mappers tsgo化に際しプラグイン機能が利⽤できなくなった。 それを置き換える形でContent mappers APIが整理中。 Vue.jsやSvelteなどの型サポートがより容易かつ⾼速に。 IPC(プロセス間通信)を⽤いる。
第3のテンプレート
TSRX React, Svelteなどに携わってきたDominic Gannaway⽒ が主導する「JSXの精神的後継」。 JSXのようにフレームワーク中⽴ながら`<style>`を使える、 分岐や反復を明⽰的に。
export function Counter() @{ const [count, setCount] = createSignal(0); const
increment = () => setCount(c => c + 1); const reset = () => setCount(0); @if (count() > 0) { <> <p>{count()}</p> <button onClick={increment}>+1</button> <button onClick={reset}>Reset</button> </> } @else { <button onClick={increment}>Start</button> } }
UIフレームワークのパフォーマンス
実⾏速度 細粒度リアクティビティがわずかに優位。 仮想DOMなアプローチではツリーの構築・差分検出が ⾼コストになりがち。
None
None
Reactの記述で速くできるか
React Compiler Reactのメモ化を⾃動で⾏う。 無駄な計算をスキップできる可能性が⾼まる。 React FirというプロジェクトもReact Confで共有されたが 情報は特に出ていない。
Octane Dominic Gannaway⽒のプロジェクト。 JSX React⾵の記述で⾼いパフォーマンスを 仮想DOMも、Signalsも無しで実現する。 状態の変化で関数コンポーネントは再実⾏される。 JSXはDOM操作のコードに変換される。
バンドルサイズ 細粒度リアクティビティが⼩さい傾向にあるものの、 仮想DOMだからといって⼤きいわけではない。 Preactは⼩さいし、Reactは⼤きい。
None
Reactはデカい
⼩型のReact ⾔わずと知れたPreact、Reactに追従できていないため、 互換とは⾔いづらい。 @tanstack/redact、ReactのAPI互換性を重視しつつ、 Transitionなどを削ることでバンドルサイズ削減を果たす。
Scheduler, Lane, Fiber, ... Reactでは、状態の更新の優先度がLaneで管理され、 タスクはschedulerに委託し、、 Fiberツリーでこれらを持ちまわり、、、 圧倒的なまでの抽象化。何を抽象化しているか?
Suspense / Transition
表と裏 タスクの始まりをユーザーに⾒せつつ、タスクの完了を待つ • useTransitionのisPendingで変更の待機を⾒せる • Suspenseで取得を待つ ユーザーの体験を損ねないための機能 →⾮同期のベースになっている
Async React
⾮同期を前提に Async ReactはReactを⾮同期に考え直すもの。 ライブラリやフレームワークも含めた⽅向性を⽰すもの。 現状のReact公式ドキュメントLearnには TransitionやSuspenseについての⾔及がない。 ドキュメントの更新もAsync Reactのスコープ。
Async **
Asynchronous Svelte Svelteの⾮同期処理をより強⼒にする提案。6で安定化予定 コンポーネントトップレベルでawaitを可能に。 ReactはユーザーがTransitionを強く意識する必要があった ⼀⽅、Svelteは⾮同期を⾃動Transitionするような仕組みに
Async Solid (Solid 2.0) v1に存在した⾮同期向けAPIは削除、 AsyncをSignalsのプリミティブとして扱う。 awaitをコンポーネント内で書かずとも、 同期処理と同様に(透過的に)⾮同期が扱える。 こちらも⾮同期を強く意識させない構造に。
function Profile(props) { const user = createMemo(() => fetchUser(props.id)); }
return ( <Loading fallback={<Skeleton />}> <h1 class={{ stale: isPending(user) }}> {user().name} </h1> </Loading> );
Async Vue ? `<Suspense>`が実験的に存在しtop-level awaitなどが可能 lazy loadもSuspenseを活⽤。 reactivity coreへの⾮同期統合はされていない。 提案⾃体は存在する。
⾮同期は誰が為に
⾮同期を扱うコンポーネント ⾮同期の仕組みがフレームワークに統合された形で 設計されたものはほぼ存在しなかった。 「データフェッチをコンポーネントで」+「SSR」 この2つを統合していく上で必要性が明らかになってきた。 所謂コロケーション。
データフェッチを扱うために • UIフレームワークからのアプローチ ◦ ◦ React - React Server Components
/ Server Functions Solid 2.0 - Server Functions ◦ ◦ ◦ TanStack Start - Server Functions Nuxt - Server Components SvelteKit - Remote Functions ◦ GraphQL Fragment Colocation • メタフレームワークからのアプローチ • フレームワーク外からのアプローチ
React Server Components Reactがライブラリの域を超えた。 Server Componentsはクライアントで実⾏されない。 データフェッチ以外もまとめて解決する。
Solid 2.0 Server Functions 所謂RPC。 TanStack Startなど、メタフレームワーク側で提供されるよ うな機能をUIフレームワークの⼀部として提供。 SolidStartというメタフレームワークは姿を消し統合。
⾮同期システムの統合
→RPCの統合
→メタフレームワークの統合
UIフレームワークの現実
Reactの圧倒的な使⽤率 2025.stateofjs.com (Usage) tanstack.com/stats (npm downloads)
Reactの圧倒的な使⽤率 2025.stateofjs.com (Usage) tanstack.com/stats (npm downloads)
Reactの圧倒的な使⽤率 2025.stateofjs.com (Usage) tanstack.com/stats (npm downloads)
Reactの圧倒的な周辺ライブラリ Vue.jsやSvelteもライブラリは健闘している。 TanStack等 複数フレームワークに対応するものも増えた。 リッチテキストエディタ、アクセシビリティ、表、D&Dなど ニッチな領域でも有⼒な選択肢がいくつかあるのがReact。
React Foundation Meta、Vercelなど複数の企業が組んでReactを⽀える体制 が整っている。 ReactはMetaだけのものではなくなった。
まとめ
これからのUIフレームワーク 「宣⾔」の範囲、「フレームワーク」の範囲、が拡⼤する。 ReactのTransitionは並⾏性の宣⾔と⾒ることができるし、 Signalsは状態の宣⾔。 UIフレームワークとメタフレームワークの距離が近くなり、 より密接になっていく。
React その確かな技術⼒、利⽤者・ライブラリの多さ、React Foundationなど盤⽯のUIフレームワーク。 Suspense/Transitionは開発者が明⽰的に取り⼊れていく 必要があり、取り⼊れられなければ恩恵が享受できない。 次々と⾰新的な技術を投⼊するReactについていけるか。
React以外 細粒度リアクティビティがトレンド。 内部に細かい差はあれど、構⽂の違いだけが⽬⽴つ状態。 SolidJSやSvelteが並⾏性や⾮同期を扱う仕組みを取り⼊れ リードしている。 パフォーマンスを追求するケースではこちらに分があるか。
おわり UIフレームワークという領域は今もなお進化を続けて、 フロントエンドという障害だらけの道を切り拓いている。 答えはないので、進化を追うのみ。 (正直枯れて欲しい気持ちも)Oo。