Reactに疲れた?Svelte 5ならコード量半減、性能は倍増(完全チュートリアル付)
なぜ今、新しいフレームワークを学ぶのか
正直に言うと、深夜にSvelteの公式サイトを開いた時、最初は乗り気ではありませんでした。「また新しいフレームワーク? どうせ中身は同じでしょ?」
私のReactプロジェクトは順調だし、わざわざ乗り換える理由なんてないと思っていました。
しかし、最初のコード例を見た時、手が止まりました。
カウンターコンポーネントを作るのに、Reactなら useState、setCount、そして「stateは直接変更してはいけない」というルールが必要です。
Svelteは? ただ let count = $state(0) と書いて、count++ するだけ。え、これだけ?
この「少なさは豊かさ(Less is More)」という衝撃に打たれ、気づけば3時間もドキュメントを読みふけっていました。
もしあなたも「フレームワーク疲れ」を感じていたり、Hooksの依存配列管理にうんざりしているなら、この記事は読む価値があります。Svelte 5がもたらす「コンパイル時最適化」というパラダイムシフトについてお話ししましょう。
Svelteとは? コンパイル時フレームワークの本質
「コンパイル時」と「実行時」の違いを、料理に例えてみましょう。
Reactは「デリバリー(出前)」です。注文すると、料理と一緒に容器、箸、ナプキン、そしてチラシまで付いてきます。これら(仮想DOM、調整アルゴリズム)は実行時に常に持ち運ぶ必要があり、たとえ「Hello World」を表示するだけでも42KBの基本パックが必要です。
Svelteは「家での自炊」です。食材を準備(コーディング)し、調理(コンパイル)してしまえば、食卓に並ぶのは純粋な「料理(原生JS)」だけ。余計な容器や道具は一切ありません。最終的なバンドルサイズはわずか1.6KBです。
私が実際に同じTodoアプリをReactとSvelteで作って比較したデータがこちらです:
300msの差は大したことないように思えますか? しかしECサイトやニュースサイトにおいて、この差は直帰率を5〜10%左右します。
Runesシステム徹底解剖:コンパイラの魔法
Svelte 5の目玉は「Runes(ルーン)」です。中二病っぽい名前ですが、使い心地は魔法そのものです。
$state:もうsetterはいらない
Reactでは:
const [count, setCount] = useState(0)
function increment() {
setCount(count + 1) // クロージャの落とし穴に注意
}
Svelte 5では:
let count = $state(0)
function increment() {
count++ // これだけ。コンパイラがリアクティビティを注入する
}
「setterはどこ?」と探す必要はありません。コンパイラが裏側で更新ロジックを自動挿入してくれるからです。これでコード量が30-40%減りました。
$derived:依存配列からの解放
useMemo の依存配列(dependency array)でバグを出したことはありませんか? 足りないと更新されず、多すぎると無駄に再計算されるあの配列です。
Svelteの $derived なら:
// React: 依存配列の手動管理が必要
const doubled = useMemo(() => count * 2, [count])
// Svelte 5: コンパイラが自動追跡
let doubled = $derived(count * 2)
複雑な計算ロジックを書くとき、この「脳内メモリを消費しない」感覚は最高です。
$effect:副作用をエレガントに
useEffect はReactで最も難解なAPIの一つです。
Svelteの $effect は直感的です:
$effect(() => {
const subscription = someAPI.subscribe()
// コンポーネント破棄時に自動クリーンアップされる
// 手動でreturnする必要なし
})
WebSocket接続やAPIポーリングなどが、驚くほどスッキリ書けます。
$props:型安全なプロパティ
<script>
let { todo, onToggle } = $props()
// TypeScript型推論が標準装備
</script>
Svelte vs React/Vue:戦いではなく選択
ここまで褒めちぎりましたが、Svelteに乗り換えるべきでしょうか?
結論:場合によります。
パフォーマンス
小規模なアプリなら差は感じません。しかし、以下のシナリオではSvelteが圧勝します:
エコシステムの成熟度
ここは圧倒的にReactの勝ちです。
- npm週間ダウンロード数:Svelte 50万 vs React 2000万
- UIライブラリの数:Reactは数百、Svelteは数十
もしあなたのプロジェクトが「ありもののUIコンポーネントを組み合わせて作る」タイプなら、Reactの方が安全です。
意思決定マトリックス
| シナリオ | 推奨 | 理由 |
|---|---|---|
| 大規模エンタープライズ | React | 人材確保、エコシステムの安定性 |
| パフォーマンス重視 | Svelte | 軽量、高速 |
| プロトタイプ/MVP | Svelte | 開発速度が速い |
| 既存Reactプロジェクト | React | 移行コストが見合わない |
30分で実践:Svelte 5でTodoアプリを作る
論より証拠。実際に作ってみましょう。
プロジェクト作成
npm create vite@latest svelte-todo -- --template svelte
cd svelte-todo
npm install
npm run dev
1. App.svelte (メインロジック)
<script>
let todos = $state([])
let input = $state('')
// 完了していないタスク数を自動計算
let remaining = $derived(
todos.filter(t => !t.done).length
)
function addTodo() {
if (input.trim()) {
// Svelte 5ならpushでOK(再代入不要!)
todos.push({
id: Date.now(),
text: input,
done: false
})
input = ''
}
}
function toggleTodo(id) {
const todo = todos.find(t => t.id === id)
if (todo) todo.done = !todo.done // 直接変更してOK
}
function deleteTodo(id) {
todos = todos.filter(t => t.id !== id)
}
</script>
<div class="app">
<h1>ToDoリスト</h1>
<div class="input-area">
<input
bind:value={input}
placeholder="新しいタスク..."
onkeydown={(e) => e.key === 'Enter' && addTodo()}
/>
<button onclick={addTodo}>追加</button>
</div>
<p>残り: {remaining} 件</p>
<ul>
{#each todos as todo}
<li>
<input
type="checkbox"
checked={todo.done}
onchange={() => toggleTodo(todo.id)}
/>
<span class:done={todo.done}>{todo.text}</span>
<button onclick={() => deleteTodo(todo.id)}>削除</button>
</li>
{/each}
</ul>
</div>
<style>
.done { text-decoration: line-through; color: #888; }
/* CSSはコンポーネントにスコープされるので安全 */
</style>
見てください、このシンプルさ。import { useState } ... もなければ、複雑な設定もありません。HTML、CSS、JSを知っていれば読めます。これがSvelteの強みです。
まとめ:騙されたと思って試してみて
SvelteがReactを完全に置き換えるとは思いません。Reactの巨大なエコシステムは依然として強力な武器です。
しかし、Svelteは**「開発の楽しさ」を思い出させてくれます**。
ボイラープレートコード(定型文)を書く時間が減り、実現したいロジックそのものに集中できる感覚。
今週末、2時間だけSvelteに投資してみませんか?
公式チュートリアル(https://svelte.dev/tutorial)を触ってみてください。
もしかしたら、その2時間があなたのフロントエンド観を永遠に変えるかもしれません。
Svelte 5で作るTodoアプリ開発フロー
Runesシステム($state, $derived)を活用したモダンなSvelteアプリケーションの実装手順
⏱️ Estimated time: 30 min
- 1
Step1: プロジェクトセットアップ
Viteを使って最速で環境構築:
npm create vite@latest svelte-todo -- --template svelte
cd svelte-todo && npm install
npm run dev - 2
Step2: リアクティブ状態の定義 ($state)
App.svelteの<script>タグ内で状態を定義:
let todos = $state([])
let input = $state('')
setter関数は不要。変数に代入するだけで画面が更新される。 - 3
Step3: 派生状態の計算 ($derived)
完了していないタスク数を自動計算:
let remaining = $derived(todos.filter(t => !t.done).length)
依存配列の指定は不要。コンパイラが自動的に依存関係を解析する。 - 4
Step4: イベント処理の実装
タスク追加ロジック:
function addTodo() {
todos.push({ id: Date.now(), text: input, done: false }); // 配列メソッドがそのまま使える
input = '';
}
HTML側:
<button onclick={addTodo}>Add</button> - 5
Step5: 双方向バインディング (bind:value)
<input bind:value={input} />
これにより、入力欄の変更が即座に変数inputに反映され、変数inputの変更も入力欄に反映される。ReactのようなonChangeハンドラは不要。
FAQ
Svelte 5とReactの決定的な違いは何ですか?
Svelte 4から5へのアップグレードは難しいですか?
Svelteは大規模開発に向いていますか?
$stateを使うとき、注意点はありますか?
3 min read · 公開日: 2025年11月24日 · 更新日: 2026年1月22日
関連記事
Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践
Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践
Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド
Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド
Next.js ユニットテスト実践:Jest + React Testing Library 完全設定ガイド

コメント
GitHubアカウントでログインしてコメントできます