Svelte 5 完全リファレンス
Claude Code / Claude Desktop等のLLMを使った開発では、公式のSvelte MCPサーバーの利用を強く推奨します。
Svelte MCPは、Svelteチームが提供する公式のModel Context Protocolサーバーで、以下の利点があります。
- 常に最新: Svelte 5とSvelteKitの公式ドキュメントから直接情報を取得
- 包括的な機能: ドキュメント検索、コード分析、自動修正提案、Playgroundリンク生成
- 公式サポート: Svelteチームによる保守
- このリファレンスとの相乗効果: MCPで最新情報を取得し、このページで体系的な理解を深める
Claude Code(CLI)でのセットアップ
# プロジェクトスコープで追加(推奨)
claude mcp add svelte -- npx -y @sveltejs/mcp
# または、グローバルスコープで追加
claude mcp add --scope user svelte -- npx -y @sveltejs/mcp 設定後、Claude Codeを再起動してください。
# 登録済みMCPサーバーの一覧を確認
claude mcp list 会話中は /mcp コマンドでも接続状態を確認できます。
Claude Desktopでのセットアップ
// claude_desktop_config.json
{
"mcpServers": {
"svelte": {
"command": "npx",
"args": ["-y", "@sveltejs/mcp"]
}
}
} 設定後、Claude Desktopを再起動してください。
Svelte 5の特徴
なぜSvelte 5なのか
- コンパイル時最適化: ランタイムオーバーヘッドを最小限に
- 仮想DOMなし: 直接DOMを操作し高速なレンダリング
- 明示的なリアクティビティ: Runesによる予測可能な状態管理
- TypeScript完全対応: 型安全な開発環境
- 少ないボイラープレート: シンプルで読みやすいコード
Runesシステム
$state - リアクティブ状態
// プリミティブ値
let count = $state(0);
let message = $state<string>('Hello');
// オブジェクト(深いリアクティビティ)
let user = $state({
name: '太郎',
age: 25,
preferences: {
theme: 'dark',
language: 'ja',
},
});
// 配列
let todos = $state<Todo[]>([]);
// クラスインスタンス
class Counter {
value = $state(0);
increment() {
this.value++;
}
reset() {
this.value = 0;
}
}
let counter = new Counter(); $state.raw - 非プロキシ状態
$state.raw は深いリアクティビティ(Proxy)を適用しない状態を作成します。大きな配列や頻繁に変更されないオブジェクトのパフォーマンス最適化に有効です。
// 大きなデータセット(Proxyのオーバーヘッドを回避)
let largeList = $state.raw<Item[]>(fetchedItems);
// 設定オブジェクト(個別プロパティの変更追跡が不要)
let config = $state.raw({
apiUrl: 'https://api.example.com',
version: '1.0.0',
});
// プロパティの変更は追跡されない
// config.apiUrl = 'new-url'; // UIは更新されない
// ✅ オブジェクト全体を置き換えることでUIを更新
config = $state.raw({ ...config, version: '1.0.1' }); 以前の $state.frozen は $state.raw にリネームされました。$state.frozen を使用している場合は $state.raw に置き換えてください。
$state.snapshot - スナップショット
let state = $state({ count: 0, items: [] });
// 現在の状態のスナップショットを取得
const snapshot = $state.snapshot(state);
localStorage.setItem('appState', JSON.stringify(snapshot)); $derived - 計算値
// シンプルな計算
let area = $derived(width * height);
// 複数の依存関係
let subtotal = $derived(price * quantity);
let tax = $derived(subtotal * taxRate);
let total = $derived(subtotal + tax); $derived.by - 複雑な計算
let processedItems = $derived.by(() => {
// フィルタリング
let filtered = items.filter((item) =>
item.name.toLowerCase().includes(filter.toLowerCase()),
);
// ソート
return filtered.sort((a, b) => {
if (sortBy === 'name') {
return a.name.localeCompare(b.name);
}
return a.price - b.price;
});
}); Overridable $derived(Svelte 5.25+)
$derived の値を一時的にオーバーライドできます。依存値が変更されると、オーバーライドはリセットされます。
// 検索候補からの入力補完パターン
let input = $state('');
let suggestion = $derived(getSuggestion(input));
// ユーザーがTabキーで候補を選択→inputが更新→suggestionがリセット
function acceptSuggestion() {
input = suggestion;
} <script lang="ts">
let selected = $state('apple');
// selectedが変更されるたびにリセットされる
let editableLabel = $derived(selected.toUpperCase());
</script>
<!-- ユーザーが直接編集可能だが、selected変更でリセット -->
<input bind:value={editableLabel} />
<select bind:value={selected}>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
</select> $effect - 副作用
// 基本的な副作用
$effect(() => {
console.log(`Count changed to: ${count}`);
document.title = `Count: ${count}`;
});
// クリーンアップ付き
$effect(() => {
const timer = setInterval(() => {
console.log('Tick');
}, 1000);
return () => clearInterval(timer);
});
// 非同期処理
$effect(() => {
const controller = new AbortController();
fetch(`/api/data?count=${count}`, {
signal: controller.signal,
})
.then((res) => res.json())
.then((data) => {
message = data.message;
});
return () => controller.abort();
}); $effect.pre - DOM更新前に実行
let value = $state('');
let previousValue = $state('');
$effect.pre(() => {
previousValue = value;
}); $effect.tracking - トラッキング確認
$effect(() => {
if ($effect.tracking()) {
console.log('This is reactive');
console.log(tracked); // 依存関係として追跡される
}
untrack(() => {
console.log(untracked); // 追跡されない
});
}); $effect.root - エフェクトスコープ
onMount(() => {
const cleanup = $effect.root(() => {
let count = $state(0);
$effect(() => {
console.log(`Count: ${count}`);
});
const interval = setInterval(() => {
count++;
}, 1000);
return () => clearInterval(interval);
});
return cleanup;
}); $effect.pending() - 非同期保留状態の追跡
$effect.pending() は、現在のコンポーネント内で非同期操作が保留中かどうかを追跡します。await expressions と組み合わせて使用します。
// await expressionsで非同期データを取得するコンポーネント内で
$effect(() => {
if ($effect.pending()) {
// ローディングスピナーの表示など
showSpinner = true;
} else {
showSpinner = false;
}
}); <svelte:boundary> の pending snippetは初回ローディングに使用します。 $effect.pending() は後続の非同期更新でのローディング状態の検出に使用します。
$props - コンポーネントプロパティ
interface Props {
title: string;
count?: number;
variant?: 'primary' | 'secondary';
onClose?: () => void;
}
let {
title,
count = 0,
variant = 'primary',
onClose,
...restProps
}: Props = $props(); childrenとSnippets
import type { Snippet } from 'svelte';
interface Props {
title: string;
children?: Snippet;
header?: Snippet<[string]>;
footer?: Snippet;
}
let { title, children, header, footer }: Props = $props(); <div class="container">
{#if header}
{@render header(title)}
{:else}
<h1>{title}</h1>
{/if}
<main>
{@render children?.()}
</main>
{#if footer}
<footer>
{@render footer()}
</footer>
{/if}
</div> $bindable - 双方向バインディング
// 子コンポーネント
interface Props {
value: string;
checked?: boolean;
}
let { value = $bindable(''), checked = $bindable(false) }: Props = $props(); <!-- 親コンポーネント -->
<ChildComponent bind:value={text} bind:checked={isChecked} /> $inspect - デバッグ
let count = $state(0);
// 開発環境でのみ動作
$inspect(count); // count: 0
// ラベル付き
$inspect('カウント', count);
// カスタムロガー
$inspect(count).with((type, value) => {
if (type === 'update') {
console.log(`Count updated to: ${value}`);
}
}); $host - カスタムエレメント
<svelte:options customElement="my-counter" />
<script lang="ts">
// カスタムエレメントのホスト要素にアクセス
$host().addEventListener('custom-event', (e) => {
console.log('Custom event received', e);
});
// ホスト要素のスタイル設定
$effect(() => {
$host().style.setProperty('--count', String(count));
});
</script> $state.eager - 非同期中の即時UI更新
ナビゲーションなどの非同期操作中でも即座にUIを更新する機能です(Svelte 5.36+)。
import { page } from '$app/state';
// 通常の$derivedはナビゲーション完了後に更新
let currentPath = $derived(page.url.pathname);
// $state.eagerはナビゲーション開始時に即座に更新
let eagerPath = $state.eager(page.url.pathname); ユースケース
<script lang="ts">
import { page } from '$app/state';
// ナビゲーション中もアクティブなメニュー項目を即座に更新
let activePath = $state.eager(page.url.pathname);
</script>
<nav>
<a href="/" class:active={activePath === '/'}>ホーム</a>
<a href="/about" class:active={activePath === '/about'}>About</a>
</nav> hydratable - SSRデータの再利用
SSRで取得したデータをハイドレーション時に再利用する低レベルAPIです。
import { hydratable } from 'svelte';
// サーバー: getUser()を実行し、結果をシリアライズしてHTMLに埋め込む
// クライアント(ハイドレーション時): シリアライズされたデータを使用
// クライアント(ハイドレーション後): getUser()を実行
const user = await hydratable('user', () => getUser()); ランダム値・時刻の安定化
// サーバーで生成されたランダム値がクライアントでも同じになる
const randomId = hydratable('random-id', () =>
Math.random().toString(36).slice(2),
);
// SSR時の時刻がハイドレーション時にも維持される
const timestamp = hydratable('page-timestamp', () => Date.now()); 通常の開発では、SvelteKitのRemote FunctionsがこのAPIを内部的に使用しています。
await expressions - 非同期構文(実験的)
Svelte 5.36+でサポートされる実験的な非同期構文です。
<script lang="ts">
// スクリプト内でのawait
const user = await fetchUser();
</script>
<!-- マークアップ内でのawait -->
<h1>{(await fetchTitle()).toUpperCase()}</h1>
<!-- $derivedと組み合わせ -->
{@const data = await $derived(fetchData(id))}
<div>{data.content}</div> svelte:boundaryとの連携
<svelte:boundary>
{#snippet pending()}
<Loading />
{/snippet}
<AsyncContent />
</svelte:boundary> ローディング状態の検出
$effect(() => {
if ($effect.pending()) {
console.log('非同期処理中...');
}
}); コンポーネント構造
基本構造
<!-- MyComponent.svelte -->
<script lang="ts">
// TypeScriptコード
import type { Snippet } from 'svelte';
// Props定義
interface Props {
title: string;
count?: number;
children?: Snippet;
}
let { title, count = 0, children }: Props = $props();
// リアクティブな状態
let internalCount = $state(count);
// 計算値
let doubled = $derived(internalCount * 2);
// メソッド
function increment() {
internalCount++;
}
</script>
<!-- HTMLテンプレート -->
<div class="component">
<h2>{title}</h2>
<p>Count: {internalCount}, Doubled: {doubled}</p>
<button onclick={increment}>Increment</button>
{@render children?.()}
</div>
<!-- スタイル -->
<style>
.component {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
}
</style> スクリプトコンテキスト
<!-- モジュールコンテキスト(一度だけ実行) -->
<script context="module" lang="ts">
let totalInstances = 0;
export function resetInstances() {
totalInstances = 0;
}
</script>
<!-- インスタンスコンテキスト(コンポーネントごと) -->
<script lang="ts">
totalInstances++;
const instanceId = totalInstances;
</script> テンプレート構文
条件分岐
{#if loading}
<p>読み込み中...</p>
{:else if error}
<p>エラー: {error.message}</p>
{:else if data}
<div>{data.content}</div>
{:else}
<p>データがありません</p>
{/if} ループ処理
<!-- 基本的なeach -->
{#each items as item (item.id)}
<Item {item} />
{/each}
<!-- インデックス付き -->
{#each items as item, index (item.id)}
<div>{index + 1}. {item.name}</div>
{/each}
<!-- 分割代入 -->
{#each users as { id, name, email } (id)}
<User {name} {email} />
{/each}
<!-- 空の場合の処理 -->
{#each items as item}
<li>{item}</li>
{:else}
<p>アイテムがありません</p>
{/each} 非同期処理
{#await promise}
<Loading />
{:then data}
<Success {data} />
{:catch error}
<Error {error} />
{/await}
<!-- 成功のみ -->
{#await promise then data}
<div>{data}</div>
{/await} キー付きブロック
{#key value}
<div transition:fade>
Value: {value}
</div>
{/key} HTMLコンテンツ
<!-- HTML文字列をレンダリング(XSS注意) -->
<div>{@html htmlContent}</div>
<!-- デバッグ出力 -->
{@debug value} Attachments - リアクティブDOM操作
Svelte 5.29+で導入されたリアクティブなDOM操作パターン({@attach})です。use:アクションと異なり、リアクティブコンテキストで動作します。
<script lang="ts">
import { createAttachmentKey } from 'svelte/attachments';
// アタッチメントキーを作成
const tooltip = createAttachmentKey();
// リアクティブな値を使用可能
let tooltipText = $state('ヒント');
</script>
<button {@attach tooltip((node) => {
// リアクティブ: tooltipTextの変更で再実行される
node.title = tooltipText;
return () => {
node.title = '';
};
})}>
ホバーしてください
</button> use:アクションとの違い
| 機能 | use:action | {@attach} |
|---|---|---|
| リアクティビティ | パラメータ変更でupdate() | 自動再実行 |
| 実行タイミング | マウント時のみ | リアクティブ値変更時 |
| クリーンアップ | destroy() | 戻り値の関数 |
外部ライブラリとの統合
<script lang="ts">
import tippy from 'tippy.js';
import { fromAction } from 'svelte/attachments';
// 既存のuse:アクションをアタッチメントに変換
const tippyAttachment = fromAction(tippy);
</script>
<button {@attach tippyAttachment({ content: 'ツールチップ' })}>
ホバー
</button> イベント処理
基本的なイベント
<!-- インラインハンドラー -->
<button onclick={() => console.log('Clicked!')}>
Click me
</button>
<!-- メソッド参照 -->
<button onclick={handleClick}>
Click me
</button>
<!-- preventDefault等は関数内で呼び出す -->
<form onsubmit={(e: SubmitEvent) => {
e.preventDefault();
handleSubmit(e);
}}>
<button type="submit">Submit</button>
</form> Svelte 4の on:click|preventDefault|stopPropagation のような修飾子構文は使用できません。 e.preventDefault() や e.stopPropagation() を関数内で直接呼び出してください。
コンポーネントイベント(コールバックProps)
Svelte 5ではコールバックpropsパターンが推奨です(createEventDispatcher はレガシー)。
// 子コンポーネント
interface Props {
onMessage?: (data: { text: string }) => void;
onDelete?: (data: { id: number }) => void;
}
let { onMessage, onDelete }: Props = $props();
function sendMessage() {
onMessage?.({ text: 'Hello!' });
} <!-- 親コンポーネント -->
<ChildComponent
onMessage={(data) => console.log(data.text)}
onDelete={(data) => removeItem(data.id)}
/> svelte/events モジュール
プログラマティックなイベントリスナー登録やメディアクエリの監視に使用します。
import { on, MediaQuery } from 'svelte/events';
// DOM要素にイベントリスナーを追加(クリーンアップ関数を返す)
const off = on(document, 'click', (e: MouseEvent) => {
console.log('Document clicked at', e.clientX, e.clientY);
});
// 解除
off();
// メディアクエリのリアクティブ監視
const isMobile = new MediaQuery('max-width: 768px');
$effect(() => {
if (isMobile.current) {
console.log('モバイルビュー');
}
}); バインディング
入力要素
<input bind:value={text} />
<input type="number" bind:value={number} />
<input type="checkbox" bind:checked />
<select bind:value={selected}>
<option value="a">A</option>
<option value="b">B</option>
</select>
<!-- グループバインディング -->
{#each items as item}
<label>
<input type="checkbox" bind:group={selectedItems} value={item} />
{item.name}
</label>
{/each} 要素プロパティ
<!-- 要素への参照 -->
<input bind:this={inputElement} />
<!-- 読み取り専用プロパティ -->
<div bind:clientWidth={width} bind:clientHeight={height}>
Resizable content
</div>
<!-- ウィンドウバインディング -->
<svelte:window
bind:innerWidth
bind:innerHeight
bind:scrollY
/> スタイリング
Scopedスタイル
<style>
/* このコンポーネントにのみ適用 */
p {
color: purple;
}
/* グローバルスタイル */
:global(body) {
margin: 0;
}
/* 子要素のグローバルスタイル */
div :global(strong) {
color: red;
}
</style> 動的スタイル
<!-- style:property -->
<div
style:color={color}
style:font-size="{size}px"
style:font-weight={bold ? 'bold' : 'normal'}
>
Style directives
</div>
<!-- CSS変数 -->
<div style:--theme-color={color}>
<p>Uses CSS variable</p>
</div> クラスディレクティブ
<!-- class:name -->
<div class:active class:important>
Conditional classes
</div>
<!-- class:name={value} -->
<div
class:active={isActive}
class:disabled={!enabled}
>
Conditional with expression
</div> 🎬 トランジションとアニメーション
ビルトイントランジション
import { fade, fly, slide, scale, blur } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
<div transition:fade={{ duration: 500 }}>
Fades in and out
</div>
<div transition:fly={{ x: 200, duration: 500, easing: quintOut }}>
Flies in
</div>
<!-- in/out別々 -->
<div in:fly={{ x: -200 }} out:fade>
Different transitions
</div> カスタムトランジション
function typewriter(node: HTMLElement, { speed = 1 }) {
const text = node.textContent!;
const duration = text.length / (speed * 0.01);
return {
duration,
tick: (t: number) => {
const i = Math.trunc(text.length * t);
node.textContent = text.slice(0, i);
},
};
} アニメーション
import { flip } from 'svelte/animate';
{#each items as item (item.id)}
<div animate:flip={{ duration: 250 }}>
{item.name}
</div>
{/each} モーション
import { spring, tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
const coords = spring(
{ x: 0, y: 0 },
{
stiffness: 0.1,
damping: 0.25,
},
);
const progress = tweened(0, {
duration: 400,
easing: cubicOut,
}); Actions
基本的なAction
function tooltip(node: HTMLElement, text: string) {
const tooltipEl = document.createElement('div');
tooltipEl.textContent = text;
tooltipEl.className = 'tooltip';
function show() {
document.body.appendChild(tooltipEl);
}
function hide() {
tooltipEl.remove();
}
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
return {
update(newText: string) {
tooltipEl.textContent = newText;
},
destroy() {
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
tooltipEl.remove();
},
};
} <button use:tooltip={'Click me!'}>
Hover me
</button> 特殊要素
svelte:self - 再帰コンポーネント
<!-- Tree.svelte -->
<script lang="ts">
interface TreeNode {
name: string;
children?: TreeNode[];
}
let { node }: { node: TreeNode } = $props();
</script>
<li>
{node.name}
{#if node.children}
<ul>
{#each node.children as child}
<svelte:self node={child} />
{/each}
</ul>
{/if}
</li> svelte:component - 動的コンポーネント
<script lang="ts">
import type { Component } from 'svelte';
let currentComponent: Component = $state(ComponentA);
</script>
<!-- Svelte 5では直接コンポーネントを動的に使用可能 -->
<svelte:component this={currentComponent} {...componentProps} /> Svelte 5では <svelte:component> なしで直接 <currentComponent /> と書くこともできます(変数名が大文字始まりの場合)。
svelte:element - 動的要素
<svelte:element this={tag} class="dynamic">
Dynamic element
</svelte:element> svelte:window, svelte:body, svelte:document, svelte:head
<svelte:window bind:scrollY onkeydown={handleKeydown} />
<svelte:body onmouseenter={() => console.log('Mouse entered')} />
<svelte:document onvisibilitychange={() => console.log('Visibility changed')} />
<svelte:head>
<title>Page Title</title>
<meta name="description" content="Page description" />
</svelte:head> TypeScript統合
コンポーネント型定義
import type { Component, ComponentProps } from 'svelte';
// Svelte 5のComponent型(推奨)
type ButtonComponent = Component<{
variant?: 'primary' | 'secondary';
disabled?: boolean;
}>;
// プロパティの抽出
type ButtonProps = ComponentProps<typeof Button>;
type NativeButtonProps = ComponentProps<'button'>;
// 組み合わせ
type CustomButtonProps = ComponentProps<'button'> & {
variant?: 'primary' | 'secondary';
size?: 'sm' | 'md' | 'lg';
}; Svelte 5では Component 型を使用します。SvelteComponent / ComponentType はレガシー互換です。
ジェネリックコンポーネント
generics 属性で型パラメータを宣言できます。
<script lang="ts" generics="T extends Record<string, unknown>">
interface Props {
items: T[];
selected?: T;
onSelect?: (item: T) => void;
}
let { items, selected, onSelect }: Props = $props();
</script>
{#each items as item}
<button onclick={() => onSelect?.(item)}>
{JSON.stringify(item)}
</button>
{/each} イベント型定義
function handleClick(event: MouseEvent & { currentTarget: HTMLButtonElement }) {
console.log(event.currentTarget.textContent);
}
// フォームイベント
function handleSubmit(event: SubmitEvent) {
event.preventDefault();
const formData = new FormData(event.currentTarget as HTMLFormElement);
} パフォーマンス最適化
untrack - 依存関係の除外
import { untrack } from 'svelte';
$effect(() => {
console.log('Trigger:', trigger);
// unrelated の変更では再実行されない
untrack(() => {
console.log('Unrelated:', unrelated);
});
}); メモ化パターン
const cache = new Map();
let filteredItems = $derived.by(() => {
const key = `${searchTerm}-${items.length}`;
if (cache.has(key)) {
return cache.get(key);
}
const result = items.filter((item) =>
item.name.toLowerCase().includes(searchTerm.toLowerCase()),
);
cache.set(key, result);
// キャッシュサイズ制限
if (cache.size > 10) {
const firstKey = cache.keys().next().value;
cache.delete(firstKey);
}
return result;
}); デバウンス処理
$effect(() => {
const timer = setTimeout(async () => {
if (searchInput.length > 2) {
const res = await fetch(`/api/search?q=${searchInput}`);
searchResults = await res.json();
}
}, 300);
return () => clearTimeout(timer);
}); flushSync - 同期的なDOM更新
import { flushSync } from 'svelte';
let count = $state(0);
function increment() {
// 通常はバッチ処理される更新を即座にDOMに反映
flushSync(() => {
count++;
});
// ここでDOMは既に更新されている
console.log(document.querySelector('#count')?.textContent); // 最新の値
} flushSync は測定やスクロール位置の調整など、DOM更新の即時反映が必要な場合に限定してください。通常の更新はSvelteのバッチ処理に任せる方がパフォーマンスが良好です。
遅延読み込み
import { onMount } from 'svelte';
import type { Component } from 'svelte';
let HeavyComponent: Component | null = $state(null);
onMount(async () => {
const module = await import('./HeavyComponent.svelte');
HeavyComponent = module.default;
}); テスト
コンポーネントテスト
import { render, fireEvent } from '@testing-library/svelte';
import { expect, test, vi } from 'vitest';
import Button from './Button.svelte';
test('renders button with text', () => {
const { getByText } = render(Button, {
props: { text: 'Click me' },
});
expect(getByText('Click me')).toBeInTheDocument();
});
test('calls onclick handler', async () => {
const handleClick = vi.fn();
const { getByRole } = render(Button, {
props: {
text: 'Click me',
onclick: handleClick,
},
});
const button = getByRole('button');
await fireEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
}); Svelte 4からの移行
主な変更点
// === 状態管理 ===
// Svelte 4
let count = 0;
$: doubled = count * 2;
// Svelte 5
let count = $state(0);
let doubled = $derived(count * 2);
// === Props ===
// Svelte 4
export let prop: string;
// Svelte 5
let { prop }: { prop: string } = $props();
// === Slots ===
// Svelte 4
<slot />
// Svelte 5
{@render children?.()} 移行チェックリスト
-
let宣言を$state()に変更 -
$:リアクティブ文を$derivedまたは$effectに変更 -
export letを$props()に変更 -
<slot />を{@render children?.()}に変更 - ストアの
$プレフィックスを削除 -
on:eventをoneventに変更(例:on:click→onclick) -
createEventDispatcherをコールバックpropsに変更 -
on:event|modifierを関数内での直接呼び出しに変更 -
$state.frozenを$state.rawに変更 -
ComponentType<SvelteComponent>をComponentに変更
関連リソース
- Svelte完全ガイド - Svelteの基礎から応用まで
- SvelteKit 2.x 完全リファレンス - SvelteKitの詳細
- 実装例 - 実践的なサンプルコード
まとめ
Svelte 5は、Runesシステムにより明示的で型安全なリアクティビティを提供します。TypeScriptとの完全な統合により、保守性が高く、パフォーマンスに優れたアプリケーションを構築できます。