はじめに:Svelte 5とRunesの登場
Svelteは、その「魔法のような」リアクティビティ(反応性)で知られてきました。letで宣言した変数を更新するだけで、コンパイラが自動的にDOMの更新を検知し、最適化されたJavaScriptコードを生成する仕組みは、多くの開発者を魅了しました。
しかし、その「魔法」は、.svelteファイルの外(例えば、+page.jsや外部のTypeScriptファイル)でリアクティブな状態を共有する際に、ストア(writable, readable)という別の仕組みを必要とするなど、いくつかの複雑さも生み出していました。
Svelte 5で導入されたRunesは、この課題を解決し、Svelteのリアクティビティをより統一的で直感的なものにするための、オプトイン(選択可能)な新機能です。
Runesは、コンパイラの「魔法」に頼るのではなく、**シグナル(Signals)**という考え方に基づいた、より明示的なリアクティビティのプリミティブを提供します。これにより、コンポーネント内でも外部のファイルでも、同じ方法でリアクティブな状態を扱えるようになります。
注: Svelte 5は現在プレビュー版です。Runesを試すには、svelte@nextをインストールし、svelte.config.jsでrunes: trueを設定する必要があります。
最短で課題解決する一冊
この記事の内容と高い親和性が確認できたベストマッチです。早めにチェックしておきましょう。
Runesの基本:$state と $derived
Runesの中心となるのが、リアクティブな状態を宣言するための$stateと、その状態から派生した値を計算するための$derivedです。
$state:リアクティブな状態の宣言
$stateは、コンポーネントの「状態(state)」を定義します。$stateで作成された変数の値が変更されると、Svelteは自動的にその変数を参照しているUIの部分を更新します。
<script>
import { $state } from 'svelte';
let count = $state(0);
function increment() {
count += 1;
}
</script>
<p>Count: {count}</p>
<button on:click={increment}>Increment</button>let count = $state(0);:countをリアクティブな状態として初期値0で宣言します。count += 1;: このように値を直接変更するだけで、UIが自動的に更新されます。
$derived:派生した状態の計算
$derivedは、他のリアクティブな状態から計算される「派生状態(derived state)」を定義します。元となる状態が変化すると、派生状態も自動的に再計算されます。
<script>
import { $state, $derived } from 'svelte';
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<p>{count} * 2 = {doubled}</p>
<button on:click={() => count++}>Increment</button>countの値が変わるたびに、doubledの値も自動的に更新され、UIに反映されます。これは、従来の$: doubled = count * 2というリアクティブ宣言に相当します。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
副作用の管理:$effect
$effectは、リアクティブな状態が変化したときに、DOMの更新以外の副作用(例:コンソールへのログ出力、APIへのデータ送信)を実行するために使います。これはReactのuseEffectに似ています。
<script>
import { $state, $effect } from 'svelte';
let count = $state(0);
$effect(() => {
// `count`の値が変化するたびにこの中のコードが実行される
console.log(`The count is now ${count}`);
// クリーンアップ関数を返す
return () => {
console.log('Cleaning up effect');
};
});
</script>
<p>Count: {count}</p>
<button on:click={() => count++}>Increment</button>$effectは、その中で参照されているリアクティブな値(この場合はcount)を自動的に追跡し、それらの値が変化したときに再実行されます。依存配列(dependency array)を指定する必要はありません。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
従来のSvelte (let と $:) との比較
Runesは、従来のSvelteの書き方をより明示的にしたものです。
| 機能 | 従来のSvelte | Svelte 5 Runes | 備考 |
|---|---|---|---|
| リアクティブな状態 | let count = 0; |
let count = $state(0); |
$stateは明示的に状態を宣言 |
| 派生状態 | $: doubled = count * 2; |
let doubled = $derived(count * 2); |
$derivedは関数呼び出し |
| 副作用 | $: console.log(count); |
$effect(() => { console.log(count); }); |
$effectはクリーンアップも可能 |
| Props | export let prop; |
let { prop } = $props(); |
$propsでProps全体を取得 |
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
Runesを使うメリットと注意点
メリット
- 統一されたリアクティビティモデル:
.svelteファイル内でも、外部の.js/.tsファイルでも、同じ$stateや$derivedを使ってリアクティブな状態(ストア)を管理できます。これにより、コードの可読性と再利用性が向上します。 - より直感的な動作: コンパイラの暗黙的な振る舞いが減り、リアクティビティがどのように機能しているかがコードから読み取りやすくなります。
- パフォーマンスの向上: Runesはより細やかなリアクティビティ追跡を可能にするため、将来的にはさらなるパフォーマンス最適化が期待されます。
注意点
- オプトイン機能: Runesはオプトインであり、既存のSvelte 4のコードはSvelte 5でもそのまま動作します。一つのプロジェクト内で両方のスタイルを混在させることも可能ですが、混乱を避けるため、コンポーネント単位でどちらかに統一することが推奨されます。
- まだプレビュー版: APIは今後変更される可能性があります。本番環境での使用は、Stable版のリリースを待つのが賢明です。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
まとめ:より直感的でスケーラブルなSvelteへ
Svelte 5のRunesは、Svelteのシンプルさとパフォーマンスを維持しつつ、そのリアクティビティモデルをより堅牢でスケーラブルなものへと進化させる、大きな一歩です。
$state, $derived, $effectといったプリミティブは、React HooksやSolidJSのシグナルの影響を受けつつも、Svelteらしいシンプルさでまとめられています。
これまでSvelteの「魔法」に少し戸惑いを感じていた開発者にとって、RunesはSvelteの世界への新しい扉を開くかもしれません。そして、長年のSvelteユーザーにとっても、より大規模で複雑なアプリケーションを構築するための強力なツールセットとなるでしょう。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。




