ReactJSとVueJSの比較 - ラウンド１： create-react-app vs create-vue

# ReactJSとVueJSの比較<br>ラウンド１： create-react-app vs create-vue
あるReactJSの案件とVueJSの案件を経験したきっかけで、ReactJSとVueJSの差異について、いくつかの懸念点がある為、アウトプットで共有したいと思います。
今回はcreate-react-appとcreate-vueを比較していきましょう。
参照のソースコード<sup>[1]</sup>は下記の参考記事に書いてあります。

**1.インストールについて：** 差異だけを比較してみます。
<table>
  <thead>
    <tr>
      <th>ReactJS</th><th>VueJS</th>
    </tr>
  </thead>
  <tr>
    <td>インストールのコマンド: <br>`npx create-react-app react-app --template typescript`</td><td>インストールのコマンド:<br>`npm create vue@3`</td>
  </tr>
  <tr>
    <td>内部に、react-scriptsを使用しています。</td><td>内部に、Viteを使用しています。</td>
  </tr>
  <tr>
    <td>ルートのライブラリーをインストールするオプションがなくて、npmで後でインストールします。</td><td>ルートのライブラリーをインストールするオプションがあります。</td>
  </tr>
  <tr>
    <td>ステート管理のライブラリー（reduxなど）をインストールするオプションがなくて、npmで後でインストールします。</td><td>ステート管理のライブラリー（Pinia）をインストールするオプションがあります。</td>
  </tr>
  <tr>
    <td>E2Eのライブラリー（Cypress）をインストールするオプションがなくて、npmで後でインストールします。</td><td>インストールするオプションがあります。</td>
  </tr>
  <tr>
    <td>一般的には、CSS-in-JSを使用します。npmでstyled-componentsをインストールします。styled-componentsはクラス衝突の現象がありません。</td><td>一般的には、CSS scoped、又は、CSS moduleを使用します。CSS scopedとmoduleはクラス衝突の現象があります<sup>[2]</sup>。</td>
  </tr>
  <tr>
    <td>PostCSSはすでにサポートされています</td><td>サポートされますが、使用したい場合、PostCSSのconfigを追加する必要があります。</td>
  </tr>
</table>

**2.記法について：**　差異だけを比較してみます。
<table>
  <thead>
    <tr>
      <th>ReactJS</th><th>VueJS</th>
    </tr>
  </thead>
  <tr>
    <td>コンポーネントをクラスとファンクションで定義します。クラスのコンポーネントとファンクションのコンポーネントは一緒に使用できます。クラスのコンポーネントの中にはファンションのコンポーネントのフックは使用できせん。　</td><td>コンポーネントをOptions APIとComposition APIで定義します。OptionsのコンポーネントとCompositionのコンポーネントは一緒に使用できません。現行のViteはCompositionしかサポートしていません。Optionsのコンポーネントのsetup()の関数の中に、Compositionの一部のフックが使用できます。</td>
  </tr>
  <tr>
    <td>クラスのコンポーネントはクラスのextend、又は、HOC<sup>[3]</sup>の形で継続できます。クラスは継続できるから、バリデーションの処理などを共通した複雑なコンポーネントが作りやすいです。　</td><td>コンポーネントはHOCの形だけで継続します。</td>
  </tr>
  <tr>
    <td>.jsx/tsxファイルの中に、複数のコンポーネントを定義できます。プライベートのコンポーネント（export・共有したくないコンポーネント）は作れます。</td><td>.vueのファイルの中に、コンポーネントは１つしか定義できません。１つのコンポーネントに対した１つのファイルなので、プライベートのコンポーネントは作れません。<br><strong>※コンポーネントは全てファイル化にしないといけない為、チームの開発には共通のルールが必要です。</strong></td>
  </tr>
  <tr>
    <td>dynamic的なコンポーネントはサポートしていませんが、Javascriptでコンポーネントを切り替えられます。dynamicにコンポーネントは作成できます。コンポーネントの中に、別のコンポーネントが作成できます<sup>[4]</sup>。</td><td>dynamicなコンポーネントはサポートしています<sup>[5]</sup>。dynamicにコンポーネントは作りにくいです。Optionsのコンポーネントの中に、getCurrentInstanceの関数で、別のOptionsのコンポーネントが作れそうですが、Compositionのコンポーネントの中に、getCurrectInstanceが使えません。<sup>[6]</sup></td>
  </tr>
  <tr>
    <td>テンプレートの中に、Javascriptの関数を使用します。例：for, ifなどはJavascriptで操作します。</td><td>テンプレートの中に、ディレクティブを使用します。例：for, ifなどはv-for, v-ifのディレクティブで操作します。ディクレティブを使いこなせる為に、ディクレティブのAPIを習得する必要があります。</td>
  </tr>
  <tr>
    <td></td><td>Typescript使用の場合、コンポーネントを作成する為に、Optionsなら、defineComponentの関数が必須で、Compositionなら、definePropsの関数が必須です。</td>
  </tr>
</table>

**3.パーフォマンスについて：**
- DOM描画の速度を測定した小さめな試験を行ってみました。
- 測定するタイミングはブラウザーのナビゲーションの開始からDOMロードの完了まで（アプリのマウントが完了した）です。ソースコードをビルドしてから、測定しました。
- 同じブラウザー（Chrome）のプライペートモードで、毎回キャッシュ削除してから実行しました。
- 測定した３つのコンポーネントはリスト(ul)です。
    - List1: 1階層のリストで１０アイテム（li）です。
    - List2: 2階層のリストで１００アイテム（li）です。
    - List3: 3階層のリストで１０００アイテム（li）です。
- 測定した結果は下記です。値は毎回の試験は変わることがありますが、イメージの為、平均の値を取りました。
<table>
  <thead>
    <tr>
      <th></th><th>ReactJS</th><th>VueJS</th>
    </tr>
  </thead>
  <tr>
    <td>List1 (1階層)</td><td>317 ms</td><td>279 ms</td>
  </tr>
  <tr>
    <td>List1 (2階層)</td><td>340 ms</td><td>393 ms</td>
  </tr>
  <tr>
    <td>List1 (3階層)</td><td>344 ms</td><td>1724 ms</td>
  </tr>
</table>

- 上記の結果から見ると、DOM描画について、いくつかのイメージがつきました。
    - コンポーネントの階層の数が少ないの場合は、ReactJSよりVueJSの方が少し早いことです。
    - コンポーネントの階層の数が多ければ多いほど、VueJSよりReactJSの方が早いことです。

**4.ステート管理について:**
<table>
  <thead>
    <tr>
      <th>ReactJS</th><th>VueJS</th>
    </tr>
  </thead>
  <tr>
    <td>Reactのstateは既存にはオブジェクトの第一階層のプロパティだけ比較して（浅い比較）、PureComponentを適用すれば、"==="で比較します。Reduxのstateの比較は"==="で比較しているから、stateを更新する時に、新規のオブジェクトを作る必要があります。<br><strong>※子コンポーネントが複数に再描画される現象があるので、パーフォマンスに著しく影響したら、useMemo<sup> [8] </sup>などのReactのフック、又は、Reduxのreselectを使用する必要があります。</strong></td><td>Vueでも、Vuex/Piniaでも、既存にはstateのプロパティがネストのオブジェクトだったら、すべてのネストのオブジェクトを比較する為、stateを更新する時に、 直接にstateのプロパティを更新します。<br><strong>※stateの構造はシンプルの場合は問題がありませんが、stateの構造がとても複雑な場合（例：APIのレスポンスの大量のリスト、階層の多すぎるデータなど）、パーフォマンスに影響がある為、shallowReactiveなどの使用は必要になります。<sup>[7]</sup></strong></td>
  </tr>
  <tr>
    <td>クラスなら、stateのプロパティで、ファンクションなら、useStateのフックで、コンポーネントのステートを管理します。</td><td>Optionsなら、dataのプロパティで、Compositionなら、変数の定義で、コンポーネントのステートを管理します。</td>
  </tr>
  <tr>
    <td>Reduxはよく使用されています。最近はRecoilがあります。RecoilはReactの最新の機能に密結合があり、非同期の処理（非同期のリクエスト送信など）に重視しているライブラリーです。ReduxからRecoilに移行する必要がありません。Reduxはクラスとファンクションの両方をサポートしていますが、Recoilはクラスのコンポーネントをサポートしません。</td><td>Vuexはよく使用されています。最近はPiniaがあります。PiniaはVuexの次のバージョンの為、VuexからPiniaに移行する必要があります。Vuex/PiniaはOptionsとCompositionの両方をサポートしています。</td>
  </tr>
  <tr>
    <td>Reduxはreact-reduxと一緒に使用します。</td><td>Vuex/Piniaは独立で使用します。</td>
  </tr>
  <tr>
    <td>Reduxのstateを更新するのはactionを通る（dispatch)しかありません。</td><td>Vuexはmutationとactionでstateを更新しますが、Piniaはmutationを廃止して、actionだけでstateを更新します。</td>
  </tr>
  <tr>
    <td>Reduxのミドルウェアの中に、stateを直接に更新できないし、次のstateの更新を停止できます。</td><td>Vuex/Piniaのプラグインの中に、stateを直接に更新できるし、次のstateの更新を停止させることができません。</td>
  </tr>
  <tr>
    <td>流行っているredux-saga、redux-observableなどのライブラリーで、データフロー（actionの発信）が制御できます。</td><td>現在流行っているライブラリーがまだないようです。</td>
  </tr>
  <tr>
    <td>流行っているredux-persistなどのライブラリーで、ローカルストレージのデータ移行が管理できます。</td><td>現在流行っているライブラリーがまだないようです。</td>
  </tr>
</table>

**5.ChatGPTによる比較:**
- ChatGPTに質問した回答をそのまま書いておきます。
> React JSとVue JSを比較してください。
>
> React JSとVue JSは両方とも人気のあるフロントエンドJavaScriptフレームワークです。以下は両者の比較です。
>
> ・コミュニティと生態系
React JSはFacebookによって開発され、大規模でアクティブなコミュニティを持っています。Reactには、様々なライブラリやツール、さまざまなチュートリアルが存在します。一方Vue JSはEvan Youによって開発された比較的新しいフレームワークであり、Reactよりも小規模なコミュニティを持ちます。ただし、Vueには便利なプラグインやツールが多く存在しています。
>
> ・コンポーネントの作成方法
Reactは、UIコンポーネントをJavaScriptの関数やクラスとして定義し、その中にHTML構造とスタイルを記述することができます。Vueは、UIコンポーネントをHTMLテンプレートとJavaScriptコードの組み合わせで定義し、コンポーネント内に含まれるスタイルをCSSで記述することができます。
>
> ・パフォーマンス
Reactは、仮想DOMの概念を導入しており、大量のデータを効率的にレンダリングできるようになっています。一方、Vueは、シンプルなテンプレート構文を持ち、高速なレンダリングを実現しています。
>
> ・学習曲線
Reactは、関数やクラスを使用してUIコンポーネントを定義するため、JavaScriptの理解が必要です。Vueは、より直感的なテンプレート構文を使用するため、より簡単に学習できる可能性があります。
>
> ・選択可能なツール
ReactとVueの両方には、豊富なライブラリやツールが存在します。ただし、Reactには多数のライブラリとツールがあり、コンポーネントの選択肢が広く、柔軟性が高いです。Vueは、生産性を向上させるための多数の便利なプラグインが用意されています。
>
> 総合的に見ると、Reactは大規模なアプリケーション開発に適しており、より高度なJavaScriptスキルが必要です。Vueはよりシンプルなアプリケーション開発に適しており、JavaScriptの知識が浅い場合でも学習が比較的容易です。

### 参考記事：
1. [参照のソースコード](https://github.com/nguyenrazona/compare-react-vue)
2. [VueJSのCSS scopedのクラス衝突](https://qiita.com/mascii/items/623d4c97c3f95e6984c0#2%E5%80%8B%E3%81%AE-data-v-xxxxxxxx-%E5%B1%9E%E6%80%A7%E3%81%AE%E4%BB%98%E4%B8%8E)
3. [HOC](https://ja.reactjs.org/docs/higher-order-components.html)
4. [ReactJSでdynamicにコンポーネントを作成する例](https://github.com/nguyenrazona/compare-react-vue/blob/main/1_react-app/src/App.tsx#L31)
5. [VueJSのdynamicなコンポーネント](https://vuejs.org/guide/essentials/component-basics.html#dynamic-components)
6. [VueJSでdynamicにコンポーネント作成](https://stackoverflow.com/questions/72031321/dynamically-create-a-component-in-vue-js)
7. [VuesJSのshallowReactiveについて](https://vuejs.org/guide/best-practices/performance.html#reduce-reactivity-overhead-for-large-immutable-structures)
8. [ReactのuseMemo](https://reactjs.org/docs/hooks-faq.html#how-to-memoize-calculations)

*※ 本記事は各ライブラリーの現在のバージョンのみを比較しています。未来は更新が必要になるかもしれません。*