Open7

Svelte Summit Fall 2023で発表されたSvelte 5の新機能や変更点

tomoamtomoam

.svelte.js/.svelte.tsファイルをコンパイル対象とし、.js/.tsファイルはコンパイル対象外となる

3:51:26~

https://www.youtube.com/live/pTgIx-ucMsY?si=dXin-cokEt941dGW&t=13886

  • Svelte 4以前のコンパイル対象は .svelte ファイルだけだったが、Runeの導入により .js/.ts ファイルもコンパイル対象としていた

    • これによって .svelte ファイルと .js/.ts ファイルで同じコードが書けるようになり、リファクタリングやコピペが楽になってDXが改善された
  • ただし、Runeはコンパイルが必要な独自機能であり、純粋な .js/.ts ではない。そのため、コンパイル対象を .svelte.js/.svelte.ts ファイルに絞ることになった

    • 純粋な js/ts ではないよ、と明示することができる
    • コンパイラの負担も減る
    • 他のフレームワークが独自のRuneを実装する場合の互換性も気にしなくて良くなる
    • 末尾は .js/.ts なので、JavaScript や TypeScript の利点は全て得られる
tomoamtomoam

Runeに関する diagnostics の追加

3:52:08~

https://www.youtube.com/live/pTgIx-ucMsY?si=jJXmesXNFuJopDA6&t=13928

  • $stateでステートを宣言し、そのステートを更新するコードが存在しない場合にメッセージが表示される
    • Svelte 5 Playground
      • count の下に波線があり、そこをホバーするとメッセージが表示される
  • ステートの最新の値を参照できるコードがない場合にメッセージが表示される
    • Svelte 5 Playground
      • count の下に波線があり、そこをホバーするとメッセージが表示される
ryoppippiryoppippi

playgroundのコードが消えてしまっているようです
追記: 環境を変えたら見られました

tomoamtomoam

class で Rune が使える

3:53:16~

https://www.youtube.com/live/pTgIx-ucMsY?si=FZ4nPB8PFweo2g9J&t=13996

まず前提として、こちらのコードには問題がある

Svelte 5 PlaygroundaddTodo 関数を要チェック

  • オブジェクトリテラルで getter/setter を使用するとメモリコストがかかるのと、通常のプロパティや通常の関数を呼び出したりするよりも遅くなる
    • V8 の誰か、どうか直してほしい。直してくれたら手作りお菓子あげるよ by Richさん
  • エルゴノミクス的にも微妙という意見、例えばPrettier に処理させるとワンライナーの get set が展開されてしまう

V8が修正されるのを待っている間に、この2つの問題を解決できないか?
そこでclassの出番。

こんなコードになる。
Svelte 5 Playground

こうするとコード量も減りパフォーマンスも良くなる。
classが嫌いなJavaScripterは多いけれど、このほうが読みやすく、メンテしやすく、デバッグしやすいとのこと。

tomoamtomoam

イベントハンドラをpropsとして渡せる

3:54:56~

https://www.youtube.com/live/pTgIx-ucMsY?si=PZrN6ZKczM-_j8bj&t=14096

なぜこの機能が必要になるのか、Svelte 4の良くない点の説明を複数のコード例を用いて丁寧に説明してくれているのですが、時間が足りないのでその部分は割愛します (きっとそのうちドキュメント化されるはず)。

ざっくり言うと、Svelteは当初Web componentsにインスパイアされてイベントハンドラとpropsを明確に区別するアプローチを取っていたが、それが原因でコンポーネントをまたぐイベントのforwardやpropagate、dispatchやdelegationが複雑になっていた、みたいなことです。

コンポーネントに対して、例えばクリックのイベントハンドラを渡すときは on:click ディレクティブではなく onclick (セミコロンなし) を使用します。

新たな機能によって改善された、にもかかわらず学ばなければいけなかったコンセプトは減った、というところがさすがです (このためにcreateEventDispatcherや on: ディレクティブを使用する必要がなくなった)。
既にSvelteを使用している人にとってはアンラーニングが必要になりますが、きっとチュートリアルが作られると思うのでなんとかなるでしょう。

tomoamtomoam

snippetの導入

4:00:59~

https://www.youtube.com/watch?v=pTgIx-ucMsY&t=14459s

インラインコンポーネントのようなものを作るための機能として {#snippet ...}{@render} という機能が追加されます。

この機能も、Svelte 4以前の良くない点を説明しながら、それを少しずつ書き換えながら説明してくれているのでYoutubeを見ていただくほうがわかりやすいと思います。

snippetはただインラインコンポーネントっぽいものを作れるだけでなく、propsとして渡すことができるようになります。渡す方法もいくつかあり、明示的に props として渡すこともできますし、自然なマークアップのように渡すこともできるし、React のような children も使えるようになります。
ポイントとしては、これによって、slot が引き起こす読みにくさやわかりにくさも改善されます。
(ちなみにこの slot も web components からインスパイアされたもので…)

書き方が増えた、と思うかもしれませんが、実際には slot 要素、slot props、slot 属性、$$slotsvelte:fragment を理解する必要がなくなるので、学習コストは減ります(これらの機能はまだ動作しますのでご安心ください)。