はじめに
2023年9月20日の夜、YouTube で以下の動画を見つけました。
Svelte 5 の新機能の紹介ということで、とても興奮しました!
Svelte 5 はまだリリース予定は決まってませんが、上記の動画のように導入予定の新機能が紹介されていたので簡単に紹介したいと思います。
ブログ
こちらのブログに上記の動画と同じことが書かれています。
しかも、既に日本語訳もされてます!
tomoam さんという方が翻訳してくれたみたいです。ありがとうございます!
Rune
読み方は "ルーン" です。
なんと既に Svelte 5 用の REPL サイトが構築されてます!
というわけで、こちら を参考に、どのような違いがあるのかを実際に動くものをお見せしたいと思います。
尚、サンプルアプリはシンプルな TODO アプリで、未完了の件数を remaining
関数を使ってリアクティブに表示しています。
まずは Rune を使わないバージョン。
<script>
let todos = [];
function remaining(todos) {
console.log('recalculating');
return todos.filter(todo => !todo.done).length;
}
function addTodo(event) {
if (event.key !== 'Enter') return;
let done = false;
let text = event.target.value;
todos = [...todos, {
done,
text
}];
event.target.value = '';
}
</script>
<input on:keydown={addTodo} />
{#each todos as todo}
<div>
<input bind:value={todo.text} />
<input type="checkbox" bind:checked={todo.done} />
</div>
{/each}
<p>{remaining(todos)} remaining</p>
追加した TODO アイテムのテキストボックスを編集するとコンソールログに recalculating
が追加されます。つまり件数に影響のない変更をしているのにもかかわらず、再レンダリングが発生しちゃってます。
Rune を使うことで改善できます。
<script>
- let todos = [];
+ let todos = $state([]);
function remaining(todos) {
console.log('recalculating');
return todos.filter(todo => !todo.done).length;
}
function addTodo(event) {
if (event.key !== 'Enter') return;
- let done = false;
- let text = event.target.value;
+ let done = $state(false);
+ let text = $state(event.target.value);
todos = [...todos, {
- done,
- text
+ get done() { return done },
+ set done(value) { done = value },
+ get text() { return text },
+ set text(value) { text = value }
}];
event.target.value = '';
}
</script>
<input on:keydown={addTodo} />
{#each todos as todo}
<div>
<input bind:value={todo.text} />
<input type="checkbox" bind:checked={todo.done} />
</div>
{/each}
<p>{remaining(todos)} remaining</p>
様々な Rune
$state
だけではなく、以下の様に様々な Rune があります。詳しくはブログや動画をご確認ください。
- $state
- $derived
- $effect
- $props
なんだか React っぽいですよね
動機(の一部)
Rune を実装する動機としては以下もあるとのことです。
前記ブログより一部を抜粋します。
実際、アプリケーションが複雑になってくるにつれ、どの値がリアクティブでどの値がリアクティブでないのか判別するのが難しくなってくるのです。また、このヒューリスティックはコンポーネントのトップレベルにある let 宣言でのみ機能するため、混乱を招く可能性があります。コードの振る舞いが .svelte ファイル内と .js で異なっていると、コードのリファクタリングが難しくなります。例えば、何かを store にして複数の場所で使えるようにする必要がある場合などです。
私は個人で小規模な開発しかしてなかったのでピンとこなかったですが、なるほどな~と思いました。
まとめ
Svelte 5 で導入予定の Rune を簡単に紹介しました。詳しくはブログ等をご確認ください。
今まで同様シンプルな実装方法は維持しつつ、状況に応じて Rune を使ってよりきめ細かにリアクティブな実装ができるようになっています。また、Rune は .svelte
ファイルだけではなく .js
ファイルでも利用できるので応用の幅が広がりそうですね。
X(旧Twitter)では様々な反響があって面白いです。
私としては今までの書き方が好きだったので、それが維持される(であろう)ことが分かってちょっとホットしました。