言語を切り替える
テーマを切り替える

Reactに疲れた?Svelte 5ならコード量半減、性能は倍増(完全チュートリアル付)

なぜ今、新しいフレームワークを学ぶのか

正直に言うと、深夜にSvelteの公式サイトを開いた時、最初は乗り気ではありませんでした。「また新しいフレームワーク? どうせ中身は同じでしょ?」
私のReactプロジェクトは順調だし、わざわざ乗り換える理由なんてないと思っていました。

しかし、最初のコード例を見た時、手が止まりました。
カウンターコンポーネントを作るのに、Reactなら useStatesetCount、そして「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で作って比較したデータがこちらです:

145KB
React版バンドルサイズ
Tree Shaking適用済み
5.2KB
Svelte版バンドルサイズ
コンパイル時最適化により96%削減
800ms
Svelte操作可能時間
3G回線下
1100ms
React操作可能時間
3G回線下

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が圧勝します:

58 FPS
Svelte 10,000件データ描画

エコシステムの成熟度

ここは圧倒的にReactの勝ちです。

  • npm週間ダウンロード数:Svelte 50万 vs React 2000万
  • UIライブラリの数:Reactは数百、Svelteは数十
    もしあなたのプロジェクトが「ありもののUIコンポーネントを組み合わせて作る」タイプなら、Reactの方が安全です。

意思決定マトリックス

シナリオ推奨理由
大規模エンタープライズReact人材確保、エコシステムの安定性
パフォーマンス重視Svelte軽量、高速
プロトタイプ/MVPSvelte開発速度が速い
既存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. 1

    Step1: プロジェクトセットアップ

    Viteを使って最速で環境構築:
    npm create vite@latest svelte-todo -- --template svelte
    cd svelte-todo && npm install
    npm run dev
  2. 2

    Step2: リアクティブ状態の定義 ($state)

    App.svelteの<script>タグ内で状態を定義:
    let todos = $state([])
    let input = $state('')
    setter関数は不要。変数に代入するだけで画面が更新される。
  3. 3

    Step3: 派生状態の計算 ($derived)

    完了していないタスク数を自動計算:
    let remaining = $derived(todos.filter(t => !t.done).length)
    依存配列の指定は不要。コンパイラが自動的に依存関係を解析する。
  4. 4

    Step4: イベント処理の実装

    タスク追加ロジック:
    function addTodo() {
    todos.push({ id: Date.now(), text: input, done: false }); // 配列メソッドがそのまま使える
    input = '';
    }
    HTML側:
    <button onclick={addTodo}>Add</button>
  5. 5

    Step5: 双方向バインディング (bind:value)

    <input bind:value={input} />
    これにより、入力欄の変更が即座に変数inputに反映され、変数inputの変更も入力欄に反映される。ReactのようなonChangeハンドラは不要。

FAQ

Svelte 5とReactの決定的な違いは何ですか?
最大の違いは「いつ仕事をするか」です。Reactはブラウザ(実行時)で仮想DOMの計算を行いますが、Svelteはビルド(コンパイル時)に仕事を行い、効率的な命令型コードを生成します。結果としてSvelteの方がバンドルサイズが小さく、初期表示が速くなります。
Svelte 4から5へのアップグレードは難しいですか?
Svelte 5は後方互換性を重視していますが、Runesシステム($stateなど)は新しい概念です。既存のSvelte 4コードも動作しますが、Runesの恩恵を受けるには書き換えが必要です。移行コストはそれほど高くなく、段階的に導入できます。
Svelteは大規模開発に向いていますか?
Svelte自体は大規模開発にも耐えうる設計ですが、エコシステム(ライブラリの豊富さ、知見の多さ)の点ではReactに劣ります。Apple、Spotify、New York Timesなどが採用していますが、ライブラリを自作する覚悟が必要な場面もあるでしょう。
$stateを使うとき、注意点はありますか?
Svelte 5の配列やオブジェクトはDeep Reactive(深く監視される)ですが、クラスのインスタンスなどを扱う場合は少し注意が必要です。基本的にはJSのオブジェクトとして扱えば直感的に動作します。

3 min read · 公開日: 2025年11月24日 · 更新日: 2026年1月22日

コメント

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

関連記事