Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TechFeed Experts Night#27 〜 フロントエンドフレームワーク最前線 (...

TechFeed Experts Night#27 〜 フロントエンドフレームワーク最前線 (Svelte)

このPDFは、Svelteというフロントエンド開発フレームワークに関する最新情報を提供するプレゼンテーションの内容をまとめたものです。主な内容は以下の通りです:

【Svelteとは】
HTMLのスーパーセットを使った、コンパイラを活用するフレームワークで、軽量なランタイムをエンドユーザーに提供します。

【チームの強化】
Dominic Gannaway(元Reactコアチームメンバー)がVercelに入社し、Svelteチームは3名になりました。

【Svelte 5の概要】

【Runes】
リアクティビティ機能が大幅に改善され、新しいマクロ方式を採用しています。これにより、依存関係の追跡がランタイムで行われるようになり、より柔軟なコードの書き方が可能になりました。

【Slot/Snippets】
JSXの利点を取り入れ、ファイル内で要素を簡単に使い回す機能を導入しました。

【イベントハンドラー】
イベントハンドリングの方法が簡略化され、パフォーマンスとメモリ効率が向上しました。

【その他の機能改善】
- テンプレート部でのTypeScript対応
- 独自のCSSパーサーの導入
- 型定義ファイルの改善:型情報が大幅に削減され、より効率的になりました。

このPDFは、Svelteの最新バージョンに関する技術的な詳細、チームの変更、そして新しい機能の実装に焦点を当てています。プレゼンテーションは、開発者がSvelte 5への移行を支援し、最新の機能と改善点を理解することを目的としています。

Yuichiro Yamashita

April 23, 2024
Tweet

More Decks by Yuichiro Yamashita

Other Decks in Technology

Transcript

  1. 強化されたチーム チームの変更 Dominic Gannaway が Vercel に入社 元 React コアチームメンバー

    lexical と inferno の作者 Vercel の Svelte チームは3 名に Rich Harris Simon Holthausen
  2. Svelte 4 Svelte 5 Reactivity App.svelte <script> let count =

    0; function increment() { count += 1; } </script> <button on:click={increment}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 12 13 ⌄ ⌄ ⌄ input output | REPL SVELTE App.svelte input output <script> let count = $state(0); function increment() { count += 1; } </script> <button onclick={increment}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 ⌄ ⌄ ⌄ PREVIEW RUNES
  3. <script> - let count = 0; + let count =

    $state(1); function increment() { count += 1; } </script> <!-- この差分については後述します --> - <button on:click={increment}> + <button onclick={increment}> clicks: {count} </button>
  4. Svelte 4 Svelte 5 Computed App.svelte <script> let count =

    0; $: doubled = count * 2; function increment() { count += 1; } </script> <button on:click={increment}> clicks: {count} </button> doubled: {doubled} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⌄ ⌄ ⌄ input output | REPL SVELTE App.svelte input output <script> let count = $state(0); let doubled = $derived(count * 2); function increment() { count += 1; } </script> <button onclick={increment}> clicks: {count} </button> doubled: {doubled} 1 2 3 4 5 6 7 8 9 10 11 12 13 ⌄ ⌄ ⌄ PREVIEW RUNES
  5. <!-- 一部抜粋 --> <script> let count = 0; - $:

    doubled = count * 2; + let doubled = $derived(count * 2); function increment() { count += 1; } </script>
  6. Svelte 4 Svelte 5 Computed (Not Working) App.svelte <script> let

    count = 0; const getDoubled = () => count * 2; $: doubled = getDoubled(); function increment() { count += 1; } </script> <button on:click={increment}> clicks: {count} </button> doubled: {doubled} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⌄ ⌄ ⌄ input output | REPL SVELTE App.svelte input output <script> let count = $state(0); const getDoubled = () => count * 2; const doubled = $derived(getDoubled()); function increment() { count += 1; } </script> <button onclick={increment}> clicks: {count} </button> doubled: {doubled} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⌄ ⌄ ⌄ PREVIEW RUNES
  7. <!-- 一部抜粋 --> <script> let count = 0; const getDoubled

    = () => count * 2; - $: doubled = getDoubled(); + const doubled = $derived(getDoubled()); function increment() { count += 1; } </script>
  8. Svelte 4 Svelte 5 Effect App.svelte <script> let count =

    0; $: { console.log({ count }); } function increment() { count += 1; } </script> <button on:click={increment}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⌄ ⌄ ⌄ ⌄ input output | REPL SVELTE App.svelte input output <script> let count = $state(0); $effect(() => { console.log({ count }); }); function increment() { count += 1; } </script> <button onclick={increment}> clicks: {count} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⌄ ⌄ ⌄ ⌄ PREVIEW RUNES
  9. <!-- 一部抜粋 --> <script> let count = 0; - $:

    { - console.log({ count }); - } + $effect(() => { + console.log({ count }); + }); function increment() { count += 1; } </script>
  10. Svelte 4 Svelte 5 Reactivity 1 App.svelte* let items [];

    function onClick() { count += 1; items.push(count); } </script> <button on:click={onClick}> clicks: {count} </button> {JSON.stringify(items)} 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ⌄ ⌄ input output | REPL SVELTE App.svelte input output <script> let count = $state(0); let items = $state([]); function onClick() { count += 1; items.push(count); } </script> <button onclick={onClick}> clicks: {count} </button> {JSON stringify(items)} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⌄ ⌄ ⌄ PREVIEW RUNES
  11. Slot / Snippets JSX が <template> よりも優れている点の1 つはファイル内で要素を簡単に使い回すことができる点です。 Svelte 5

    では、このJSX の利点を取り入れることに成功しました。 const data = ["Alice", "Bob", "Charlie", "David"]; const renderItemElement = (name) => <div key={name}>{name}</div>; return ( <div> <div>{data.map(renderItemElement)}</div> </div> ); <script> const data = ["Alice", "Bob", "Charlie", "David"]; </script> {#Snippet item(name)} <div>{name}</div> {/Snippet} {#each data as name} {@render item(name)} {/each}
  12. App.svelte Child.svelte Result JS output CSS output AST output Message

    from child component! Console CLEAR <script> import Child from './Child.svelte'; </script> {#snippet item(name)} <div>{name}</div> {/snippet} <Child {item} /> 1 2 3 4 5 6 7 8 9 ⌄ WORK IN PROGRESS! PREVIEW • • Docs Status Svelte RUNES
  13. Svelte 4 Svelte 5 Reactivity App.svelte <script> let count =

    0; function increment() { count += 1; } </script> <button on:click={increment}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 12 13 ⌄ ⌄ ⌄ input output | REPL SVELTE App.svelte input output <script> let count = $state(0); function increment() { count += 1; } </script> <button onclick={increment}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 ⌄ ⌄ ⌄ PREVIEW RUNES
  14. App.svelte Result JS output CSS output AST output clicks: 0

    Console CLEAR <script> let count = $state(0); function onclick() { count += 1; } </script> <button {onclick}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 ⌄ ⌄ ⌄ WORK IN PROGRESS! PREVIEW • • Docs Status Svelte RUNES
  15. App.svelte Child.svelte Result JS output CSS output AST output Click

    Child Component clickCount: 0 dblclickCount: 0 Console CLEAR <script> import Child from './Child.svelte'; let clickCount = $state(0); let dblclickCount = $state(0); function onclick() { clickCount += 1; } function ondblclick() { dblclickCount += 1; } </script> <Child {onclick} {ondblclick} /> <div> clickCount: {clickCount} </div> <div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ⌄ ⌄ ⌄ ⌄ ⌄ WORK IN PROGRESS! PREVIEW • • Docs Status Svelte RUNES
  16. イベントハンドラー Svelte 4 では、各DOM にイベントがアタッチされていました Svelte 5 では、アプリケーションルートにのみイベントをアタッチします 一般的に Event

    delegation と呼ばれる手法です これは、React や Solid で用いられている手法です イベントのアタッチは時間のかかる処理であるため、特に大規模なDOM でレンダリング速度やハイドレーショ ン速度に違いが出るはずです。 また、メモリ使用量にも良い影響があるはずです。 非ドキュメント情報
  17. App.svelte Result JS output CSS output AST output Alice Bob

    Charlie David Console CLEAR <script lang="ts"> const data = [{ name: "Alice" }, { name: "Bob" }, { nam </script> {#each data as user} {@const name: string = user.name } <li>{name}</li> {/each} 1 2 3 4 5 6 7 8 ⌄ ⌄ WORK IN PROGRESS! PREVIEW • • Docs Status Svelte RUNES
  18. CSS パーサー Svelte 4 までは、 css-tree を使用してスタイル部を解析していました Svelte 5 では、独自のコードで

    CSS を解析しています Svelte コンパイラは、CSS セレクタ部は重要ですが、宣言部は基本的に何もする必要がありません よって、一般的なCSS パーサーよりも簡易なパーサーで充分でした これにより将来のCSS の新仕様に対して簡単に対応できる可能性が高まりました また、当時コンテナクエリをサポートするCSS パーサーはありませんでした 更に、このメリットを活かして、子コンポーネントにスタイルを渡す方法を検討しています ( 遂に! 🎉) 非ドキュメント情報
  19. 型定義ファイル Svelte 5 では dts-buddy というライブラリを使用して型を自動生成しています これにより、1.1MB あった型情報が 25KB になりました

    また、関数から宣言先に飛ぶ際、型宣言ではなく関数自体に飛べるようになりました🎉 参照: https://github.com/sveltejs/svelte/pull/8702 非ドキュメント情報
  20. HTML のスーパーセットとしての Svelte このコードをブラウザで表示すると... このようにレンダリングされます… しかし Svelte 4 はこうレンダリングしていました… <div>

    などの 非 void HTML タグは自己終了できません Svelte 5 は <div /> のようなコードを警告するようになりました 参考: https://github.com/sveltejs/svelte/pull/11114 非ドキュメント情報 <div /> hello! <div>hello!</div> <div></div> hello!
  21. Svelte 4 からの移行 Svelte 5 は Svelte 4 までの機能をサポートしています 1

    コンポーネントずつ漸進的に移行可能です 実際に私も個人的に管理している SvelteKit アプリを移行しましたが、ライブラリバージョンを Svelte 5 に 上げただけでも正しく動作しました Svelte 5 では Svelte 4 までのテストが通ることを確認しています 詳細は ステータスページ から確認可能です
  22. App.svelte Result JS output CSS output AST output clicks: 0

    Console CLEAR <script> let count = 0; function increment() { count += 1; } </script> <button on:click={increment}> clicks: {count} </button> 1 2 3 4 5 6 7 8 9 10 11 12 13 ⌄ ⌄ ⌄ WORK IN PROGRESS! PREVIEW • • Docs Status Svelte RUNES
  23. まとめ ( 今日ご紹介したもの) ( チーム体制) 元 React コアチームのメンバーが参加しフルタイム3 名体制になった (

    リアクティビティ) 依存関係の追跡がランタイムになったことで柔軟性が向上した js/ts ファイルでもリアクティビティを使用できるようになった Array / Map の破壊メソッドの利用でもリアクティブになった 高度な機能も登場し、必要に応じてより細かな制御も可能になった ( 新しい slot) Snippets によりSvelte コンポーネント内で再利用可能な部品を定義できるようになった ( イベントハンドラー) 記述が単純になり柔軟性が向上した createEventDispatcher は不要になった イベントのアタッチがトップ要素に移譲されることで性能・メモリ効率が向上した U コンポーネントは任意のイベントを受け付け可能になった テンプレート部の TypeScript 対応 自作のCSS パーサーを採用 型定義ファイルの改善 Svelte 4 から漸進的に移行可能
  24. その他 SvelteKit: https://kit.svelte.dev/ SvelteKit ( 日本語版): https://kit.svelte.jp/ ESLint Plugin Svelte:

    https://github.com/sveltejs/eslint-plugin-svelte 今日紹介できませんでしたが Next.js / Nuxt の Svelte 版である SvelteKit も 昨年末にメジャーバージョンアップをしました。 こちらも一度ドキュメントを参照ください。 また Svelte 用の ESLint Plugin も提供しているので 是非ご活用ください