フレームワークの差が戦力の決定的差ではない

## 気に入ったぞSvelte！
筆者は、三つのフロントエンド開発フレームワークに触れてきました。VueとReact（厳密にはnextjs）は実際に業務に使い、独学でSvelteも運用してました。なぜSvelteを始めたのかというと、ホームページに「他のフレームワークよりコードの書く量が減るよ！」と書いてあって、実際にそれが本当かを確かめるために興味本位でやりました。

最終的には業務に持っていって、記述量が少ないフレームワークに徐々に置き換えて **みんなハッピー！** という未来を目指していました。

#### ここではReact、Vue、Svelteの三つを比べながら、結局何を使えばいいの？という質問に個人的な結論を出したいと思います。

例えば、全てのフレームワークで表示に載ってる「ボタンクリックしてカウンターを増やす」簡単なコードをそれぞれのフレームワークで書いてみました。

#### React
```react
import React, { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

export default App;
```
#### Vue
```vue
<template>
  <div>
    <p>You clicked {{ count }} times</p>
    <button @click="incrementCount">Click me</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    incrementCount() {
      this.count++;
    }
  }
};
</script>
```
#### Svelte
```vue
<script>
  let count = 0;

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

<div>
  <p>You clicked {count} times</p>
  <button on:click={incrementCount}>Click me</button>
</div>
```

これだけを見ると、Svelteは同じことをより少ない数のコードで成し遂げています。それもそうです、他二つと違って、Svelteはコンパイル型のフレームワークなので、ブラウザの負担が少なく、他では書けなかったことを手短に書けるのが特徴的です。

ページ遷移しない簡単なウェブサイトを作るだけならSvelteで十分事足ります。しかし、業務の話になるとそう簡単にはいきません。
## 趣味とは違うのだよ、趣味とは

実際に業務を行う場合は考えなければいけないことが多く増えてきます。

- ページ遷移のrouter実装
- 共通で使うコンポーネント作成
- フロントエンドとバックエンドを繋ぐ
- テストを書く

などなど、いくらSvelteが軽いとはいえ、全部一人で書くと正直だるいです。そんな時に、救世主としてやってくるのが「共通ライブラリ」です。

これらは本来フレームワークが無い機能や共通のライブラリやUIコンポーネントを提供することで、ユーザが自らコーディングする必要のある量を減らします。

VueだとVuetify、ReactだとMaterialUIがあるように、Svelteにも複数のライブラリがあります。ここだと当時使ったSveltestrapを例に出します。

上のカウンターを増やすコードに、それぞれのUIライブラリ

#### React+MaterialUI
```react
import React, { useState } from 'react';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';

function App() {
  const [count, setCount] = useState(0);

  return (
    <div style={{ padding: '20px' }}>
      <Typography variant="h6">You clicked {count} times</Typography>
      <Button variant="contained" color="primary" onClick={() => setCount(count + 1)}>
        Click me
      </Button>
    </div>
  );
}

export default App;
```

#### Vue+Vuetify
```vue
<template>
  <v-app>
    <v-container>
      <v-row>
        <v-col>
          <v-btn color="primary" @click="count++">
            Click me
          </v-btn>
          <p>You clicked {{ count }} times</p>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  data: () => ({
    count: 0
  })
};
</script>
```

#### Svelte+sveltestrap
```vue
<script>
  import { Button } from 'sveltestrap';
  let count = 0;
</script>

<div style="padding: 20px;">
  <Button color="primary" on:click={() => count++}>Click me</Button>
  <p>You clicked {count} times</p>
</div>
```

必要な共通コンポーネントをインポートして、それを使うだけです。そうすると、ユーザが実際に書くロジックはそのページやコンポーネントの独自の物だけで済みます。上記の例でもSvelteの方が短いですが、配置の自由度という意味では、細かにグリッドシステムで制御してるvueの方が後々のCSSを記述する時には楽です。

router機能だけでいうと、それぞれにもインポート可能なrouterが存在します。

このように、共通コンポーネントさえあれば、コーディングする量は極端に減ってきます。

## 共通コンポーネントの性能のお陰だということを忘れるな

つまりは、業務上で記述量を減らすにはフレームワークよりは、以下のことが大事になります。

- 適切にコンポーネント化されたデザイン
- 使いまわしやすい共通コンポーネント

例えば、ボタンひとつを配置するときに、毎回CSSの修正を入れたり、中身の機能をその場で書き換えても最終的には共通コンポーネントの意義がありません。
適切にコンポーネント化し、かつ、使いまわしがしやすくて、その場で余分な修正が発生しないようにプロジェクトを分割したり共通UIライブラリを使えるのであれば **フレームワークはなんでも良い** ということになります。

実際に筆者は前職ではコンポーネント化はされているけれども、同じプロジェクトでデザインが微妙に変更されて機能拡張が依頼されていたため、常に共通コンポーネントの機能やCSSに修正が発生してました。いくら「早い・軽い」フレームワークに切り替えても、プロジェクト本体が抱えている問題は解消しません。

#### 結論

これから新しいプロジェクトを始める時はフレームワーク単体の性能そのものではなく、自分が何を最終的な着地点としているかで考えれば良いです。

- 手短に「モダンな」サイトを作りたい　→ UIライブラリがあって自分が一番扱いやすいフレームワークでOK
- クライアント用に１からプロジェクト作りたい　→ バックエンドとの接続、求めるルーティング機能を提供してくれるライブラリを持ったものを選んでOK（普通にReactとVueで良い）
- サーバ側の負担を極端に減らしたい　→ Svelte一択、だけど色々と痒いところに手が届かない

将来性としてはSvelteは一目を置けるものではあるものの、Reactの巨大なコミュニティを持っていることからくるアドバンテージにはまだまだ勝てないです。Svelteの少し特殊な記法もまだ人気が無いので、性能は申し分ないけど、実際の業務で扱えるかどうかはデザインやコンポーネント化にかかっています。

以上です、自分が三つのフレームワークを触ってみて思った雑感でした。