Svelte でゲーム音楽検索サイト作った話

# 概要
私は [ゲーム音楽](https://video-game-music.net/) というサイトを個人開発 & 運営しています。
この記事では Svelte を中心に書いていきます。

https://video-game-music.net

# 結論
[Svelte](https://svelte.dev) は素晴らしい。[XState](https://xstate.js.org/docs/), [Tailwind CSS](https://tailwindcss.com/) との相性が抜群過ぎて、私は今のところこの組み合わせ以外は考えられないほどです。今後は Svelte も選定候補に上がると思います。
ちなみにフロントエンドのリポジトリはこちら。

https://github.com/himanushi/music-client-v3

バックエンドはこちら。

https://github.com/himanushi/music-server

# なぜ Svelte は素晴らしいの？
Svelte は軽い早いで知られていますが、使ってみると他の良さがありました。

## 1. Reactivity が素晴らしい
Svelte で開発する前、このサイトでは React で開発していました。React には React hooks という革命的な技術があります。簡単に言うと、クラスを書かずとも use〇〇 という関数をコンポーネント内で使用し、変数の変更を検知をしてコンポーネント内を再レンダリングするという仕組みです。簡単なコンポーネントであれば hooks で事足ります。ファットなコンポーネントを作ろうとすると(そもそもファットにすべきじゃないが)、レンダリングし過ぎてしまうことがあります。これを回避するためには、 useMemo などメモ化することで無駄に処理を実行させない方法があります。
React の性能を上げるにはメモ化することを考えなければいけません(私の実装が悪く性能が悪いと言うのもあります)。どの関数を useCallback するのかなど考えるのが割と大変です。
しかし、 Svelte はその逆です。どの処理をリアクティブにするのかを考えるだけで良いのです。リアクティブにしたい場合は以下のようにします。

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

// リアクティブではない
// これは1度だけ "0だよ!" と表示されるだけ
console.log(`${count}だよ!1回だけだよ!`);

// リアクティブ
// count が変更される度に実行される
$: {
  console.log(`${count}だよ!`);
}

// リアクティブだが count がスコープ内に存在しないので1度しか実行されない!賢い。
$: {
  console.log("元気だよ!");
}

// 条件付きリアクティブ
// count が10以上だと実行される
$: if (count >= 10) {
  console.log("10以上だよ!");
}

const onClick = () => count += 1;
</script>

<button on:click={onClick}>
  カウント {count}
</button>
```

`$` の書き方のクセはありますが、慣れるとかなり便利です。
このように `$` のスコープ内だけ更新されると直感的に理解できて素晴らしいです。

## 2. Scoped CSS が素晴らしい
Svelte は、 script と style と component を同ファイルにまとめてかけます。
component は script タグと style タグ以外が component として扱われます。

```html
<script>
let count = 0;
const onClick = () => count += 1;
</script>

<button on:click={onClick}>
  カウント {count}
</button>

<style>
button {
  display: block;
  width: 160px;
  height: 160px;
}
</style>
```

ここで、 「えっ、 button にスタイル書いたら全ての button タグに反映されるのでは?」と思う方もいるかもしれません。実は、 Svelte には Scoped CSS という仕組みがあります。そのためこのファイル内の button タグにしかこの style は適用されません。とてもスッキリしますね。
この Svelte ととても相性が良いのが、 [Tailwind CSS](https://tailwindcss.com/) です。Tailwind CSS は、簡単に言うとよく使う CSS class を集めたCSSフレームワークです。そのため、以下のように書けます。

```html
<script>
let count = 0;
const onClick = () => count += 1;
</script>

<button class="block h-40 w-40" on:click={onClick}>
  カウント {count}
</button>
```

このようにインラインスタイルでかけます。とても省略された CSS class です。私のようなインラインスタイル派ではない人のための style タグの書き方もあります。

```html
<script>
let count = 0;
const onClick = () => count += 1;
</script>

<button on:click={onClick}>
  カウント {count}
</button>

<style>
button {
  @apply block h-40 w-40
  /* Tailwind CSS 2.1 からは以下の書き方もできる */
  @apply block h-[160px] w-[160px]
}
</style>
```

とてもスッキリしますね。
この Scoped CSS には弱点があり、動的に生成されたHTMLには適用されません。その場合に効果的なのが、[Tailwind CSS Typography](https://github.com/tailwindlabs/tailwindcss-typography) です。

```html
<div class="prose">
  {@html markdown}
</div>
```

このように class に "prose"　を指定するだけでおしゃれなスタイルが効きます。
Scoped CSS は CSS ファイルと JavaScript ファイルとで行き来すると何がなんだかわからなくなりがちな私にとっては素敵な仕組みです。

## 3. Stores が素晴らしい
Svelte ではフロントエンドで困りがちな Redux などの store ライブラリの選定をしなくても問題ありません。 
Svelte stores という store がフレームワークレベルで組み込まれています。
以下のように使います。

https://svelte.jp/tutorial/writable-stores

store を生成した後は `$count` のようにするだけで、どのコンポーネントで変更されてもリアクティブに変更されます。

> [オブジェクトが subscribe メソッドを正しく実装していれば、それはストアです。](https://svelte.jp/tutorial/custom-stores)

これはわかりやすい。
この Svelte stores は、奇跡的に [XState](https://xstate.js.org/docs/) と[相性が抜群に良い](https://xstate.js.org/docs/recipes/svelte.html)です。 XState とはステートマシンを実装することが出来るようになるライブラリです。 ロジックは XState で作り込み、表示は js と css で作り込むだけで済みます。例えば、SPAで実装した時、共通したマシンを使用したいときは、

```ts
export const service = interpret(nanikasiranoMachine).start();
```

のように XState で service を生成するだけで、 あとは、 `$service`　と書いておくだけでリアクティブ対象になります。これ本当に奇跡。
なぜ `$service` でリアクティブになるのかというと、 XState のサービスオブジェクトが subscribe メソッドを正しく実装しているからです！すごい！すごいぞ！
Svelte と XState の実装についての話し合いとかあったの？ Svelte のために作ったの？　ってぐらいの奇跡。
XState メインの記事は別で書きます。
このように Stores がとても便利です。

## 4. アニメーションが素晴らしい
Svelte ではアニメーションがフレームワークレベルで存在します。
とっても便利！

https://svelte.jp/tutorial/animate

# 終わりに
後半尻すぼみすぎなんですが、このあたりにしておきます。
Svelte は素晴らしすぎるので、ぜひ皆さんも [チュートリアル](https://svelte.jp/tutorial/basics) を学んで Svelte に足を踏み入れましょう！