Svelte 5: コンパイラー主導のアプローチとメンタルモデル
ビルド時に完全に消える JavaScript フレームワークを想像してください。ダウンロードするライブラリはありません。 仮想 DOM は実行時に調整され、フレームワークのオーバーヘッドはブラウザーのインスペクターに表示されません。これ Svelte: 伝統的な意味でのフレームワークではなく、 .svelte コンポーネントを変換するコンパイラ 純粋で最適化された JavaScript で。 2024 年 10 月にリリースされた Svelte 5 は、このモデルを 世界に革命をもたらした普遍的な信号ベースの反応性システムである Runes でレベルアップ アプリケーションの状態を管理する場所。
React、Vue、または Angular から来ている場合、Svelte のメンタル モデルには視点を変える必要があります。それはそれではない 新しい API を学習しますが、フレームワーク自体は実行時には存在しないことを理解する必要があります。このガイドはあなたに役立ちます Svelte コンパイラーが内部でどのように動作するのか、なぜ Runes なのかを探りながら、そのメンタル モデルを構築します。 は、このアプローチの自然な進化を表しています。
何を学ぶか
- Svelte コンパイラーがコンポーネントを純粋な JavaScript に変換する方法
- Svelte には仮想 DOM が必要ないため
- Svelte 5 を使用するための正しいメンタル モデル
- ルーンとシグナルベースの反応性の概要
- React および Vue とのパフォーマンスの比較 (2025 ~ 2026 年のデータ)
- Runes を使用して最初の Svelte 5 コンポーネントを作成する方法
仮想 DOM の問題
Svelte が存在する理由を理解するには、まず Svelte が何を解決するのかを理解する必要があります。 React、Vue、Angular はすべて 仮想DOM: フレームワークが計算に使用する実際の DOM のメモリ内表現 違い (diffing) を確認し、必要な変更のみを適用します。このアプローチは直感的に理にかなっています - そして DOM を直接操作するよりも、メモリ内の表現を更新する方が効率的ですが、コストがかかります hidden: 何も変更されていない場合でも、仮想 DOM 調整は常に行われます。
Svelte の作成者である Rich Harris は、「仮想 DOM は純粋なオーバーヘッドです"で コミュニティで活発な議論を引き起こした 2019 年の記事。重要なのは、仮想 DOM ではありません。 全体的に遅いですが、コンパイラーが除去できる不要な作業が発生します。
カウンターを表示する React コンポーネントを考えてみましょう。
// React: il virtual DOM riconcilia ad ogni render
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Contatore: {count}</p>
<button onClick={() => setCount(count + 1)}>
Incrementa
</button>
</div>
);
}
状態が変化するたびに、React は次のことを行う必要があります。 コンポーネントの新しい仮想 DOM を作成し、それを比較します。 前の DOM との比較 (差分)、何が変更されたかを判断し、最後に実際の DOM を更新します。コンパイラ Svelte はビルド時に、何が変更される可能性があるのか (段落のテキストのみ) をすでに認識しており、それを直接生成します。 コードを使用して、中間手順を行わずに更新します。
Svelte コンパイラーの仕組み
Svelte コンポーネントと .svelte これには、スクリプト、テンプレート、および
スタイル。ビルド中に、コンパイラーはこのファイルを解析し、ファイルを直接操作する JavaScript を生成します。
DOM、きめ細かな外科的更新を備えています。
<!-- Counter.svelte - Il componente sorgente -->
<script>
let count = $state(0);
</script>
<p>Contatore: {count}</p>
<button onclick={() => count++}>
Incrementa
</button>
コンパイラはテンプレートを分析し、次のことを理解します。 {count} そして唯一変わる部分。
生成された JavaScript には次のものが直接含まれます。 ノードの作成 <p>、テキストノードを挿入し、
次の場合にのみそのテキスト ノードを更新するエフェクトを登録します。 count 変化。仮想 DOM はありません。
相違も和解もありません。
コンパイルされたコードを簡略化すると、次のようになります。
// Output del compilatore Svelte (semplificato)
import { mount, text, element } from 'svelte/internal';
export function Counter(target) {
let count = 0;
const p = element('p');
const countText = text(`Contatore: ${count}`);
const button = element('button');
button.addEventListener('click', () => {
count++;
// Aggiorna SOLO il text node specifico
set_data(countText, `Contatore: ${count}`);
});
append(p, countText);
append(target, p);
append(target, button);
}
これがコンパイラ主導のアプローチの核心です。コンパイラは、何を変更し、何を生成できるかを正確に認識しています。 実行時にこの作業を汎用の差分アルゴリズムに委任するのではなく、最適なコードで処理します。
バンドル サイズの比較 (2025 年)
同等の TodoList コンポーネントは、主要なフレームワーク間で非常に異なるサイズの JavaScript バンドルを生成します。
- React 19 + ReactDOM: gzip 圧縮された ~42 KB (ランタイムを含む)
- Vue 3.5: gzip 圧縮された ~22 KB (ランタイムを含む)
- Angular 19 (スタンドアロン): gzip 圧縮された ~35 KB (ランタイムを含む)
- クイック 5: gzip 圧縮された ~2 ~ 5 KB (ランタイムなし、コンポーネントのみ)
For large applications with many components, the advantage is reduced because each Svelte component includes その更新コード。 But for medium-sized applications, Svelte remains the overall winner ブラウザへのペイロードの観点から。
Svelte 5 のパラダイム シフト: ルーン
Svelte 4 は、ブロック内のすべての変数の割り当てに基づいた魔法の反応性システムを使用しました。
<script> 自動的にリアクティブになり、コンパイラーは依存関係を全体的に追跡しました。
ビルド。これは単純なケースではうまく機能しましたが、重要な制限がありました。
.svelte コンポーネント内のみであり、魔法のような動作によりコードの推論が困難になりました。
Svelte 5 の紹介 ルーン文字: 接頭辞が付いた特殊関数 $ コミュニケーションを取る人
コンパイラを直接使用します。ルーンは通常の機能ではありません — $state() それは関数ではありません
これはインポートして呼び出しますが、コンパイラによって認識される特殊な構文です。 useState()
React では、lint と型チェックのためにトランスパイラーによって認識されますが、実際には通常の関数です。
主な違い: ルーン文字は機能します どこでも.svelte ファイルだけでなく:
// counter.svelte.ts - Un modulo TypeScript puro con reattivita Svelte 5
export function createCounter(initial: number = 0) {
let count = $state(initial);
// $derived calcola automaticamente quando count cambia
const doubled = $derived(count * 2);
const isEven = $derived(count % 2 === 0);
function increment() { count++; }
function decrement() { count--; }
function reset() { count = initial; }
return {
get count() { return count; },
get doubled() { return doubled; },
get isEven() { return isEven; },
increment,
decrement,
reset
};
}
// Usabile in qualsiasi componente .svelte
// o in altri file TypeScript che importano questo modulo
これは Svelte 4 と比較して根本的な変更です。反応性を備えたビジネス ロジックは生き続けることができます。 個別の TypeScript モジュールで、コンポーネント間で共有可能、通常の単体テストと分離してテスト可能、 レンダリング環境に依存しない。
4 つの基本的なルーン
Svelte 5 では、ほとんどのユースケースをカバーする 4 つの主要なルーンが導入されています。
<script lang="ts">
// $state: stato reattivo (sostituisce let reattivo di Svelte 4)
let name = $state('Federico');
let items = $state<string[]>([]);
// $derived: valori computati (sostituisce $: di Svelte 4)
const greeting = $derived(`Ciao, ${name}!`);
const itemCount = $derived(items.length);
// $effect: side effects (sostituisce $: con side effects di Svelte 4)
$effect(() => {
console.log('name cambiato:', name);
// Cleanup automatico quando l'effetto si ri-esegue
return () => console.log('cleanup prima del prossimo run');
});
// $props: props del componente (sostituisce export let di Svelte 4)
const { title, onClose = () => {} } = $props<{
title: string;
onClose?: () => void;
}>();
</script>
Svelte 4 と Svelte 5: 主な違い
Svelte 4 の経験がある場合は、ルーンによって構文が大幅に変更されます。
- クイック 4:
let count = 0;(暗黙の魔法) → クイック 5:let count = $state(0);(明示的に) - クイック 4:
$: doubled = count * 2;→ クイック 5:const doubled = $derived(count * 2); - クイック 4:
export let prop;→ クイック 5:const { prop } = $props(); - クイック 4:
on:click={handler}→ クイック 5:onclick={handler}
Svelte 5 は「レガシー モード」で Svelte 4 との下位互換性を維持しているため、移行は段階的に行うことができます。
Svelte 5 と React: 実用的な比較
アプローチの違いを具体的に理解するために、React と Svelte 5 に実装された同じコンポーネントを見てみましょう。
// React 19: SearchBox con debounce
import { useState, useEffect, useCallback } from 'react';
function SearchBox({ onSearch }: { onSearch: (q: string) => void }) {
const [query, setQuery] = useState('');
const [debouncedQuery, setDebouncedQuery] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedQuery(query);
}, 300);
return () => clearTimeout(timer);
}, [query]);
useEffect(() => {
if (debouncedQuery) onSearch(debouncedQuery);
}, [debouncedQuery, onSearch]);
return (
<input
value={query}
onChange={e => setQuery(e.target.value)}
placeholder="Cerca..."
/>
);
}
<!-- Svelte 5: SearchBox con debounce -->
<script lang="ts">
const { onSearch }: { onSearch: (q: string) => void } = $props();
let query = $state('');
$effect(() => {
const timer = setTimeout(() => {
if (query) onSearch(query);
}, 300);
return () => clearTimeout(timer);
});
</script>
<input bind:value={query} placeholder="Cerca..." />
Svelte 5 バージョンがより簡潔なのは、それが「魔法」だからではなく、コンパイラーが同期を管理するためです。
の間 query そして経由して入力します bind:value、 そして $effect 自動的に追跡する
依存 query 依存関係配列で明示的に宣言する必要はありません。
実際のパフォーマンス: データとベンチマーク
合成ベンチマークは誤解を招くことがよくありますが、 JS フレームワーク ベンチマーク 2025 (集中的な DOM 操作を伴う実際のハードウェアで実行) Svelte 5 が常に上位 4 分の 1 に入る テスト済みのほぼすべての操作:
- 10,000 行を作成: Svelte 5 ~1.2x 対 Vanilla JS、React ~2.1x オーバーヘッド
- 10 行ごとに更新します。 Svelte 5 ~1.1x、React ~1.8x
- 行のハイライトを選択します。 Svelte 5 ~1.05x、React ~1.4x
- 作成後の記憶: Svelte 5 は React よりもメモリ使用量が約 40% 少ない
この利点は、JavaScript の解析と実行が行われるローエンドのモバイル デバイスで最も顕著になります。 それらはより高価です。最新のデスクトップでは、一般的なアプリケーションの実質的な違いは目に見えないことがよくあります エンドユーザーへ。
最初のクイック プロジェクトの作成 5
Svelte 5 を使い始める最も簡単な方法は、Svelte をベースにした公式のフルスタック フレームワークである SvelteKit を使用することです。
# Crea un nuovo progetto SvelteKit con Svelte 5
npm create svelte@latest my-svelte-app
cd my-svelte-app
# Seleziona: Skeleton project, TypeScript, ESLint, Prettier
npm install
# Avvia il dev server
npm run dev
をチェックして、プロジェクトが Svelte 5 を使用していることを確認します。 package.json:
{
"dependencies": {
"@sveltejs/kit": "^2.5.0",
"svelte": "^5.0.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"vite": "^5.0.0"
}
}
ルーンを使用して最初のコンポーネントを作成します src/lib/components/Hello.svelte:
<script lang="ts">
// $props: tipo sicuro per le props del componente
const { name = 'Mondo' }: { name?: string } = $props();
// $state: stato locale reattivo
let clickCount = $state(0);
// $derived: valore computato da state e props
const message = $derived(
clickCount === 0
? `Ciao, ${name}!`
: `Ciao, ${name}! Hai cliccato ${clickCount} volt${clickCount === 1 ? 'a' : 'e'}`
);
</script>
<div class="hello">
<p>{message}</p>
<button onclick={() => clickCount++}>
Clicca qui
</button>
</div>
<style>
.hello {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
}
button {
margin-top: 0.5rem;
padding: 0.5rem 1rem;
}
</style>
SvelteKit: フルスタック フレームワーク
単独で UI レイヤーのみをクイックします。 SvelteKit Svelte 上に構築されたアプリケーション フレームワーク これにより、ルーティング、SSR (サーバーサイド レンダリング)、SSG (静的サイト生成)、フォーム アクション、および負荷が追加されます。 データを取得するための関数。 React の Next.js または Vue の Nuxt に相当します。
SvelteKit プロジェクトの構造は、ファイルベースの規則に従います。
src/
├── routes/
│ ├── +layout.svelte # Layout globale
│ ├── +page.svelte # Homepage (/)
│ ├── about/
│ │ └── +page.svelte # Pagina /about
│ └── blog/
│ ├── +page.svelte # Lista articoli (/blog)
│ ├── +page.server.ts # Data fetching server-side
│ └── [slug]/
│ ├── +page.svelte # Articolo singolo (/blog/nome)
│ └── +page.server.ts
├── lib/
│ ├── components/ # Componenti condivisibili
│ └── utils/ # Utilita
└── app.html # Template HTML base
Svelte 5 を選択する場合
Svelte 5 は、次の場合に最適な選択肢です。
- アップロードのパフォーマンスは重要です (モバイル、低速接続)
- バンドルのサイズは最小にする必要があります
- チームは React とは異なるメンタル モデルを学ぶことに意欲的です
- 定型文を減らして優れた DX (開発者エクスペリエンス) を実現したい
- SvelteKit を使用して SSR/SSG のメリットを享受できる、コンテンツの多いサイトを構築します。
Svelte 5 は、次のような場合には適切な選択ではない可能性があります。
- チームには React の豊富な経験があり、移行には多大な費用がかかります
- 多くの UI コンポーネント ライブラリが求められています (React エコシステムはより広範です)
- React を使用するライブラリ (ヘッドレス UI、Radix など) と統合する必要があります。
メンタルモデル: 心に留めておくべきこと
Svelte 5 を使用するには、フレームワークと比較したいくつかの基本的な違いを理解する必要があります 仮想 DOM に基づいて:
- コンパイラはツールであり、ランタイムではありません。 何かがうまくいかないとき ご想像のとおり、レンダリング ループではなく、コンパイラーがコードをどのように解釈するかを考えてください。
-
ルーンはコンパイラーと通信します。
$state(),$derived()他の関数は単純な関数ではありません。これらは、反応性を処理する方法についてのコンパイラーへの指示です。 -
応答性は設計により細分化されています。 実際に存在するもののみを迅速に更新します
変わりました。手動で最適化するメカニズムはありません
useMemoouseCallback. -
.svelte.ts ファイルにより、ユニバーサルな応答性が可能になります。 ルーンはどの分野でも使用できます
拡張子付きのファイル
.svelte.tso.svelte.jsコンポーネントだけではありません。
結論と次のステップ
Svelte 5 は、フレームワークの作成以来最も重要な進化を表しています。アプローチ コンパイラ駆動は新しいものではありませんが、Rune はコンポーネントの範囲外でシグナルベースの応答性を実現します。 より柔軟でテスト可能なアーキテクチャ パターンが可能になります。その結果、以下を組み合わせたフレームワークが生まれます。 優れたパフォーマンス、最小限のバンドル、無駄な定型文のない開発者エクスペリエンス。
シリーズの次の記事では、さらに詳しく説明します。 $state と $derived: 仕組み
Proxy ES6 経由の優れた応答性、たとえば $derived メモ化の実装とその方法
コンポーネント間で共有される TypeScript ファイルで Runes を使用します。
シリーズ: Svelte 5 およびフロントエンド コンパイラー駆動
- 第 1 条 (本): コンパイラ主導のアプローチとメンタルモデル
- 記事 2: $state と $derived — ルーンとの普遍的な反応性
- 第 3 条: $effect とライフサイクル — いつ使用するか (および使用しない場合)
- 第 4 条: SvelteKit SSR、ストリーミングおよびロード機能
- 第 5 条: Svelte 5 のトランジションとアニメーション
- 第 6 条: Svelte のアクセシビリティ: コンパイラーの警告とベスト プラクティス
- 第 7 条: グローバル状態管理: コンテキスト、ルーン、ストア
- 第 8 条: Svelte 4 から Svelte 5 への移行 — 実践ガイド
- 第 9 条: Svelte 5 でのテスト: Vitest、テスト ライブラリ、および Playwright







