Vue・Reactを超える！？ 近年話題の Svelte に入門してみよう！

# はじめに
今回は最近ちょいちょい使われているフロントエンドフレームワーク Svelte.jsについて解説します[^1]。
最近だと、ロイターの大統領選挙ページで使われてましたね。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751408/8825c7c8-dfed-8843-669d-322adfe624c2.png' width='550'>

Svelte.jsは速くて軽く、簡単に実装できるフレームワークです。

どうやら、React, Vue, Angular, Emberよりも速いらしいです！
https://svelte.dev/blog/frameworks-without-the-framework#Introducing_Svelte



Tutorialも充実しており、サイト上で実際に書きながら学ぶこともできます。

本記事はTutorialを触る前に、ざっと概要を学びたい方向けに書いてます！



# YouTube動画
動画で確認したい方はこちらもどうぞ。
[【YouTube動画】 VueやReactを超える！？ 次世代のフロントエンドフレームワーク Svelte.jsをご紹介！！](https://youtu.be/rbhMST4A1Hs)
[![VueやReactを超える！？ 次世代のフロントエンドフレームワーク Svelte.jsをご紹介！！](https://img.youtube.com/vi/rbhMST4A1Hs/0.jpg)](https://youtu.be/rbhMST4A1Hs)


# 基本の書き方
それでは基本の書き方をみていきます。
Tutorialを始める前に、さらっと読んでおくと理解が捗ると思います！

## 変数の使い方
svelte.jsでは、scriptタグ内でletを定義するだけで変数として利用できます。

```html
<!-- svelte.js -->
<script>
  let name = 'World';
</script>

<h1> Hello, { name } !! </h1>
```

Vue.jsで同じように出力しようとすると、以下のようになります。
svelteと比較して、記述量が多めです。

```vue
<!-- vue.js -->
<template>
  <h1> Hello, {{ name }} !! </h1>
</template>

<script>
export default {
  data() {
    return {
      name: "World"
    }
  } 
}
</script>
```

## 属性の使い方

属性の書き方も簡単です！
vueで画像を表示しようとすると次のようになります。

```vue
<!-- vue.js -->
<template>
  <img :src="image" alt='yassun youtube' />
</template>

<script>
export default {
  data() {
    return {
      image: "https://img.youtube.com/vi/rbhMST4A1Hs/0.jpg",
    };
  },
};
</script>
```

svelteだともっと簡単に書くことができます。
ちなみに、altを省略すると、A11y (<b>A</b>ccessibilit<b>y</b>) の警告が出てきます。

```html
<!-- svelte.js -->
<script>
  let src="https://img.youtube.com/vi/rbhMST4A1Hs/0.jpg"
</script>


<main>
  <img {src} alt='yassun youtube'>
</main>
```

## styleの書き方
styleに直接記述するだけで、スタイルを当てることができます。
また、デフォルトでスコープがコンポーネント内になるため、クラス名の競合を意識しなくて大丈夫です。

```html
<!-- svelte.js -->
<style>
  p {
    color: purple;
  }
</style>

<p>テスト！</p>
```

## 他コンポーネントの使い方
インポートするだけで使えます。

```html
<script>
  import Nested from './Nested.svelte'
</script>

<Nested />
```


## Reactive
on:イベントでイベント発火条件を書き、scriptタグ内のメソッドを呼び出すだけで、メソッドが使えます。
vueのようにmethodsを定義する必要がありません。

```html
<script>
  let count = 0;

  function handleClick() {
    count += 1;
  }
</script>

<button on:click={handleClick}>{ count }</button>
```

preventDefaultやstopPropagationの追加もパイプで繋ぐだけで、簡単にできます。

```html
<script>
  function handleForm() {
    console.log('handleForm');
  }
</script>

<form on:submit|preventDefault={handleForm}>
  <button>ボタン</button>
</form>
```

ある変数と連動して別のコードが動いて欲しい場合には、$:を使います。
例えば、scriptタグに以下のように書くと、countが変化した時にコンソールにログが流れます。

```javascript
let count = 0;

$: console.log(`count: ${count}`);
```

変化するコードをグルーピングしたい場合は{}で括ります。

```javascript
let count = 0;

$: {
  console.log('hello');
  console.log(`count: ${count}`);
}
```

ifで別途、コードが連動する条件を指定することもできます。
以下の場合は、countが2以上になったら、動きます。

```javascript 
let count = 0;

$: if (count >= 2) {
  console.log(`count: ${count}`);
}
```


## props
propsはscript内でexportするだけで、別のコンポーネントで使えるようになります。
exportする際にデフォルト値を指定することもできます。

```html
<!-- Child.svelte -->
<script>
 export let answer;
</script>

<p>{ answer }</p>
```

```html
<script>
  import Child from './Child.svelte'
</script>

<Child answer={10} />
```


## slot
slotはこんな感じで入れます。

Comp.svelte

```html
<div>
  <slot></slot>
</div>
```

App.svelte

```html
<script>
  improt Comp from './Comp.svelte'
</script>

<Comp>
  <div>スロット</div>
</Comp>
```

## if
if文はこのように書きます。
/ifでif文の終わりを決めます。

```html
{#if count > 10 }
  <p>Big!!</p>
{:else if count > 5 }
  <p>Medium</p>
{:else}
  <p>Small</p>
{/if}
```

## await
awaitはif文と似たような感じで書けます。

```html
{#await promise}
  <p>waiting...</p>
{:then number}
  <p>number is {number}</p>
{:catch error}
  <p>{error.message}</p>
{/await}
```

## loop (each)
for文に慣れていると間違えそうですが、`cats as cat`というように、各要素はasの右側に書きます。

```html
{#each cats as cat, i}
  <div>{i}-th cat is {cat}</div>
{/each}
```

## bind
bindはvueっぽく書けます。

```html
<input bind:value={name}>
```

## Lifecycle
ライフサイクルのメソッドは以下のように、svelteからインポートして使います。
onMount, onDestroy, beforeUpdate, afterUpdate, tickなどが用意されています。

```html

<script>
  import { onMount } from 'svelte';

  let test = '';

  onMount(async () => {
    test = await somePromise();
  })
</script>

<p>{ test }</p>
```

## Store
storeもsvelteに入っているため、以下のようにして使うことができます。
writable(0)をセットすることで、値のupdate, set, subscribeが使えるようになります。

他にもsvelte/storeには、読み込み専用のreadableや別のstoreを使って新しくstoreを作るderivedなどがあります。

```javascript
import { writable } from 'svelte/store';

export const test = writable(0);

test.update(n => n + 1)
test.set(x)
test.subscribe(value => {})

{ $test }
```

以下のようにメソッドを制限したカスタムstoreを作成することもできます。
ここら辺の詳しい話もTutorialに詳細があるので、ぜひ確認してみてください。

```javascript
function createCount() {
  // writable(0)をセットし、メソッドを呼び出す
  const { subscribe, set, update } = writable(0);

  return {
    subscribe,
    // 値を1だけ増やすメソッドを設定
    increment: () => update(n => n + 1),
    // 値を1だけ減らすメソッドを設定
    decrement: () => update(n => n - 1),
    reset: () => set(0)
  };
}
```

# おわりに
Svelte.jsを試してみたくなりましたか？
簡単に始めることができるので、ぜひ試してみてください！

Tutorialはこちら
https://svelte.dev/tutorial/basics

自由に触りたい方は以下の方法もオススメです！
Svelteの公式ページでREPLを試す。
https://svelte.dev/repl

CodeSandboxのSvelte.jsのテンプレートを試す。
https://codesandbox.io/dashboard/home

npxでローカルにインストールして試す。
https://svelte.dev/blog/the-easiest-way-to-get-started

[^1]: 公式サイトでもフレームワークと名乗っているので、フレームワークという語を使います。https://svelte.dev/blog/frameworks-without-the-framework#Introducing_Svelte