日本ではJavaScriptのフレームワークと言えばVueが人気でしたが、ここ最近はReactの波が来ている印象です。そんな中、Svelteという単語を目にしました。
調べてみると、State of JS 2020で満足度・関心のランキングで1位を獲得しており、勢いのあるフレームワークです。
今回はそんなSvelteについて紹介します。
目次
Svelteとは
SvelteはWebアプリケーションやUIを構築するためのコンパイラです。
公式サイトでは3つの特徴を挙げています。
Write less code
Virtual DOM is pure overhead
Truly reactive
ReactやVueは仮想DOMを作成し、実際のDOMと仮想DOMの差分のみをDOMに反映しています。
それに対してSvelteは、コンパイル時にデータの変更に応じてDOMを書き換えるJavaScriptファイルが生成されます。
そうすることでバンドルサイズが軽量になり、パフォーマンスが向上します。
個人的にリアクティブシステムがすごいと思いました。
以下のように記述するだけで、ボタンを押せば変数countが更新されていきます。
1 2 3 4 5 6 7 8 9 10 | <script> let count = 0; const increaseCount = () => count++; </script> <button on:click={increaseCount}>ボタン</button> <p>ボタンを{count}回押しました</p> |
ReactではuseStateフック、Vueではdataプロパティを使用するのに対して、シンプルな記述でリアクティブな動きが実装できます。
導入方法
Svelteをサクッと試してみたいという場合はREPLを利用してみましょう。ブラウザ上で簡単にSvelteを動かすことができます。
ローカルで動かすにはNode.jsをインストールしていない方はダウンロードしてください。
エディターにVS Codeを使用している場合はプラグインのSvelte for VS Codeをいれておくと、便利です。
では以下を参考にSvelteを導入します。
以下のコマンドで、npmのライブラリの1つdegitをインストールしたのち、Svelteのリポジトリをコピーします。
1 2 3 4 | npm install degit npx degit sveltejs/template プロジェクト名 |
degitを導入しない場合は、GitからZipをダウンロードします。
そしてダウンロードしたファイルを解凍し、プロジェクトの場所に置いてください。
上記2つのどちらで配置したら、以下のコマンドを打ちます。
TypeScriptを導入したい場合は、コメントアウトしている記述を入力してください。
1 2 3 4 5 6 7 | cd my-svelte-project # node scripts/setupTypeScript.js npm install npm run dev |
http://localhost:5000を開くと、画像のように表示されていれば導入完了です。
ディレクトリ構造
テンプレートは以下のようなディレクトリ構造になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | プロジェクト名 ├── README.md ├── package.json ├── package-lock.json ├── rollup.config.js ├── .gitignore ├── node_modules ├── public │ ├── favicon.png │ ├── index.html │ ├── global.css │ └── build │ ├── bundle.css │ ├── bundle.js │ └── bundle.js.map ├── scripts │ └── setupTypeScript.js └── src ├── App.svelte └── main.js |
基本的にファイルを操作するのはpublicフォルダとsrcフォルダになります。
まずpublic/index.htmlを見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!DOCTYPE html> <html lang="en"> <head> <meta charset='utf-8'> <meta name='viewport' content='width=device-width,initial-scale=1'> <title>Svelte app</title> <link rel='icon' type='image/png' href='/favicon.png'> <link rel='stylesheet' href='/global.css'> <link rel='stylesheet' href='/build/bundle.css'> <script defer src='/build/bundle.js'></script> </head> <body> </body> </html> |
bodyが空ですが、実際には文字などが表示されています。
次にsrc/App.svelteを見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <script> export let name; </script> <main> <h1>Hello {name}!</h1> <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p> </main> <style> /* 省略 */ </style> |
このコンポーネントに記述されている内容がページに表示されています。
src/main.jsがアプリケーションのエントリーポイントです。body要素にAppコンポーネントを描画しています。
1 2 3 4 5 6 7 8 9 10 11 12 | import App from './App.svelte'; const app = new App({ target: document.body, props: { name: 'world' } }); export default app; |
基本構文
コンポーネントを拡張子がsvelteのファイルに記述します。
svelteファイル内ではHTML・CSS・JavaScriptが記述できます。
styleタグ内で記述したスタイルは、そのコンポーネント内でのみ適用されます。
1 2 3 4 5 6 7 8 9 10 11 | <script> // コンポーネント内の処理記述 </script> <!-- HTML記述 --> <style> /* コンポーネントのスタイル記述 */ </style> |
では基本的な記法について紹介します。
変数の描画
1 2 3 4 5 6 7 8 9 | <script> let name = 'world'; let src = '/img/image.jpg'; </script> <h1>Hello {name}!</h1> <img {src} alt=""> |
{}内はJavaScriptのコードを置き換えられて、表示されます。
src=”{src}”のように属性の名前と値の変数が一致する場合、{src}のように省略して書けます。
ディレクティブとバインディング
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <script> let firstName = ''; let lastName = ''; $: fullName = `${firstName} ${lastName}`; </script> <input type="text" bind:value={firstName}> <input type="text" bind:value={lastName}> <p>氏名:{fullName}</p> |
$:内は参照する値が変わるたび、このコードを再実行します。
今回だと変数firstNameとlastNameの値が変更した場合、fullNameが自動的に変更されます。
ディレクティブはブロックのように書くこともできます。
1 2 3 4 5 6 7 | <script> $: { // 処理 } </script> |
フォームの入力欄など、どちらかを変更すれば片方もまた更新されるバインディングはbind:属性名={連携したい変数名}のように記述します。
ちなみに、Svelteのリアクティブシステムは代入がトリガーとなります。
pushやspliceのような配列メソッドを使った場合、自動的に値が更新されません。
その場合以下の解決方法があります。後者の方がメジャーです。
1 2 3 4 5 6 7 8 9 10 | <script> // 配列メソッド使用後に代入 numbers.push(numbers.length + 1); numbers = numbers; // スプレッド構文を使用する numbers = [...numbers, numbers.length + 1]; </script> |
ifブロック
SvelteはHTMLの表示を制御できます。
条件分岐によって表示するHTMLを変更したい場合は、ifブロックを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <script> let isLogin = false; </script> <button on:click={() => isLogin = !isLogin}> {#if isLogin} ログアウト {:else} ログイン {/if} </button> |
#:/とタグの最初の記号が全部違い、変な感じがするかもしれません。
記号の規則は表のようになっています。
記号 | 意味 |
---|---|
# | ブロックの開始タグ |
: | ブロックの継続タグ |
/ | ブロックの終了タグ |
eachブロック
HTML要素を繰り返したい場合はeachブロックを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <script> let cats = [ {id: 1, name: 'たま'}, {id: 2, name: 'みけ'}, {id: 3, name: 'くろ'}, ] </script> <ul> {#each cats as cat, index (cat.id)} <li>{index + 1}: {cat.name}</li> {/each} </ul> |
要素を追加したり、削除する場合は(keyにする値)で識別子を渡す必要があります。
これによりコンポーネントが更新されたときに、どの要素を変更するのか特定します。
イベントハンドラ
script内に記述した関数を実行したい場合は、イベントハンドラを以下のように定義します。
1 2 3 | <button on:click|イベント修飾子={実行したい関数名}></button> |
要素にon:ディレクティブを使用すると、イベントの登録ができます。
またイベントハンドラに修飾子を設定すると、イベントのふるまいを変更できます。
イベント修飾子について詳しく知りたい方は公式のドキュメントを見てみてください。
他のコンポーネントを使用する
コンポーネントの中で別のコンポーネントを使用したい場合、importを記述します。
1 2 3 4 5 6 7 8 | <script> import コンポーネント名 from '現在のコンポーネントから、読み込みたいコンポーネントファイルへの相対パス' </script> <コンポーネント名 /> |
こうすると他のコンポーネントに記述した内容が、<コンポーネント名 />の場所に表示されます。
コンポーネント名は頭文字を大文字で書いてください。小文字から始めた場合、SvelteはHTMLタグと認識します。
Props
親コンポーネントから子コンポーネントに渡す値のことをPropsといいます。
子コンポーネント側でPropsとして受け取りたい変数の前にexportを記述します。
1 2 3 4 5 6 7 | <script> import Button from './Btn.svelte'; </script> <Button disabled={false}/> |
1 2 3 4 5 6 7 8 9 10 | <script> export let disabled; // 初期値を定義 export let disabled = false; </script> <button {disabled}></button> |
JavaScriptのexportは外部からモジュールとして読み込むために使用します。
それに対してSvelte内のexportは宣言した変数が親コンポーネントで公開されていることを表しています。
意味がほぼ逆なので、最初は混乱するかもしれません。
また初期値を定義していると、親からpropsが渡されなかった場合にその値を参照します。
まとめ
Svelteは他のフレームワークに比べて、周辺ライブラリやエコシステムがまだ成熟していません。
ですが以下のような利点もあり、個人開発やファイル制限があるプロジェクトなどで活躍できるのではないでしょうか。
バンドルサイズの軽量さ
少ないコード量で実装できる
他のフレームワークに比べると学習難易度が低い
興味が湧いてきた方は、公式のチュートリアルが手厚いので触ってみてください。
また以下の記事が学習リソースについてまとめられているので、紹介いたします。
参考サイト
Svelte • サイバネティクスで強化されたWebアプリ
Getting started with Svelte – Learn web development | MDN
Svelteに入門した | フューチャー技術ブログ
Svelteで始める頑張らないフロントエンド生活 前編
Svelteとは
The Svelte Handbook