【Vue.js】エラー「failed to load config from /app/vite.config.ts」が出た場合の対処法（@esbuild/darwin-arm64とは？）

# 概要
- Vue.jsのdockerコンテナを起動したところ、`failed to load config from /app/vite.config.ts...`というエラーが表示されてしまいました。本記事では、その解決方法を記載します。

# 前提
- Apple M1 Pro
- node：v18.16.0
- npm：9.5.1
- dockerコンテナでVue.jsのアプリ起動

### Vue.jsとは
- フロントエンドのJavaScriptフレームワークの1つ
- データの変更が自動的にビューに反映され、ビューの変更もデータに反映されるため、手動でDOMを更新する必要がないのが特徴（高速なレンダリングパフォーマンス）
- 「データの変更を自動で画面に反映する」については、以下のサイトから引用させていただきます
    - 出典元：[Vue.jsとは、どんなことができるフレームワーク？特徴と勉強方法をカンタン解説【入門編】](https://www.webstaff.jp/guide/trend/vuejs/)


> Vue.jsは、MVCモデルから派生したMVVMモデルを採用したフレームワークで「Model」「View」「ViewModel」の3つの機能で設計されています。

> Modelはデータの管理や保存、外部との入出力や内部的な操作などのロジックに関わる処理を担い、Viewはユーザーの入力や操作を受け付けて、画面表示などのUIに関わる処理を担うものです。そして、ModelとViewの状態を監視しているのがViewModelで、状態に変化があれば必要に応じてそれぞれに通知します。また、このようなロジックとUIを分離して状態を監視しながら処理がおこなえるのは、仮想DOMによるものです。

### `node_modules`と`package.json`
- `node_modules`：Node.jsプロジェクトで使用されるパッケージの依存関係が格納されるディレクトリ
    - ルートディレクトリ内に自動的に作成され、パッケージマネージャ（npmやYarnなど）によって管理されることが多い
- `package.json`：プロジェクトのメタデータや依存関係の管理に使用されるファイル。パッケージマネージャはこれらの依存関係を解決し、関連するパッケージやライブラリを`node_modules`ディレクトリにダウンロード・インストールする。
- つまり`package.json`が依存関係を定義するファイル、`node_modules`が依存関係のコードが格納される場所、ということですね

# エラー全文
- dockerがうまく起動せず、起動しては落ちる、を繰り返していました。
- `docker logs`に記載のあるエラーログは以下です。

```
> app@0.0.0 dev
> vite

failed to load config from /app/vite.config.ts
error when starting dev server:
Error: 
You installed esbuild for another platform than the one you're currently using.
This won't work because esbuild is written with native code and needs to
install a platform-specific binary executable.

Specifically the "@esbuild/darwin-arm64" package is present but this platform
needs the "@esbuild/linux-arm64" package instead. People often get into this
situation by installing esbuild on Windows or macOS and copying "node_modules"
into a Docker image that runs Linux, or by copying "node_modules" between
Windows and WSL environments.

If you are installing with npm, you can try not copying the "node_modules"
directory when you copy the files over, and running "npm ci" or "npm install"
on the destination platform after the copy. Or you could consider using yarn
instead of npm which has built-in support for installing a package on multiple
platforms simultaneously.

If you are installing with yarn, you can try listing both this platform and the
other platform in your ".yarnrc.yml" file using the "supportedArchitectures"
feature: https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures
Keep in mind that this means multiple copies of esbuild will be present.

Another alternative is to use the "esbuild-wasm" package instead, which works
the same way on all platforms. But it comes with a heavy performance cost and
can sometimes be 10x slower than the "esbuild" package, so you may also not
want to do that.

    at generateBinPath (/app/node_modules/esbuild/lib/main.js:1874:17)
    at esbuildCommandAndArgs (/app/node_modules/esbuild/lib/main.js:1955:33)
    at ensureServiceIsRunning (/app/node_modules/esbuild/lib/main.js:2119:25)
    at build (/app/node_modules/esbuild/lib/main.js:2011:26)
    at bundleConfigFile (file:///app/node_modules/vite/dist/node/chunks/dep-e8f070e8.js:64411:26)
    at loadConfigFromFile (file:///app/node_modules/vite/dist/node/chunks/dep-e8f070e8.js:64387:31)
    at resolveConfig (file:///app/node_modules/vite/dist/node/chunks/dep-e8f070e8.js:63993:34)
    at _createServer (file:///app/node_modules/vite/dist/node/chunks/dep-e8f070e8.js:63274:26)
    at createServer (file:///app/node_modules/vite/dist/node/chunks/dep-e8f070e8.js:63271:12)
    at CAC.<anonymous> (file:///app/node_modules/vite/dist/node/cli.js:733:30)
```

# 原因：`node_modules`内のファイルが上書きされていた
- エラーの内容は「esbuildパッケージが異なるプラットフォーム向けにインストールされていることが原因でアプリが起動しない」ことを言っているようです。`arm64`あたりのエラーは以前も別件で見たことがあったのですが、M1チップが原因だったような...また面倒な環境問題かな？と思っていたのですが、あっさり解決しました。
- 原因は、`docker-compose.yaml`にありました。

### エラー発生時
```docker-compose.yaml
    volumes:
      - ./frontend/app:/app
      - /frontend/app/node_modules
```

- 何が原因だったかというと、`node_modules`ディレクトリが含まれた`./frontend/app`ディレクトリ全体をコンテナにマウントしていたからです。これにより、ディレクトリ内のネイティブバイナリファイルが上書きされてしまい、esbuildパッケージの正しいバイナリが使用できなかったと考えられます。

### esbuildとは？
- 高速なJavaScriptおよびTypeScriptのバンドルおよびトランスパイルツール
- 実行には以下のようなプラットフォーム固有のバイナリファイルが必要
    - `@esbuild/darwin-arm64`: macOSのM1チップ搭載のコンピュータ向けのバイナリパッケージ
    - `@esbuild/linux-arm64`: LinuxのARM64アーキテクチャ向けのバイナリパッケージ
- 正しいバイナリをインストールすることで、esbuildは正常に動作します

### viteとは？
- [Vite | 次世代フロントエンドツール](https://ja.vitejs.dev/)
- 高速なウェブ開発用のビルドツール（フランス語で「速い」という意味らしい）
- `ES modules`と呼ばれるモジュール分割の仕組みを使い、モジュール間の依存関係解決が高速に行う→コードを素早くブラウザに配信できる。
- `vite.config.ts`: Viteの設定ファイル。開発サーバーやビルドプロセスの設定、プラグインの追加などをカスタマイズできる。設定例は以下の公式ドキュメントにあります。
    - [Vite の設定](https://ja.vitejs.dev/config/)


# 解決方法
- 以下で解決しました。

```docker-compose.yaml
    volumes:
      - ./frontend/app/src:/app/src
      - /frontend/app/node_modules
```

- `./frontend/app/src`ディレクトリのみを`/app/src`にマウントし、`/frontend/app/node_modules`はマウントされないようにしました。これにより、esbuildパッケージのバイナリファイルは正しい状態で保たれ、アプリが正常に起動できるようになりました。
- ネイティブバイナリファイルが特定のプラットフォームに依存している、というのポイントだったんですね（`docker-compose.yamｌ`の書き方もあるけど）。
- 今回のエラーは、正しいバイナリが使用できなかったために発生するエラーだと思われますので、同様の事象の方はぜひ確認ください。