nvmを使ったNode.jsのバージョン管理で詰まって時間を溶かした話

## はじめに
業務でTypeScriptとReactを使って新しくプロジェクトを作ることになりました。
その際、Node.jsのバージョンを普段使っているものと異なるものにする必要があったため、nvmを使用しました。
そこで悪戦苦闘し、時間を溶かしてしまったのでその経緯を記録として残します。

## 要はしょうもないミス
長くなるので先に結論から書いておくと、原因は以下の2点に集約されます。
* `nvm`を入れる前に、Node.jsをアンインストールするべきだった
* `volta`というバージョン管理をすでに導入していたのを忘れていた

どちらも初歩的なミスですが、これに気づかずかなりの時間うんうんうなっていました。
では、解決のために何をしたのかを書いておきます。

## やったこと
### viteの導入
```bash
yarn create vite
```
これは成功

### 依存関係のインストール
```bash
yarn
```
ここで以下のように失敗
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/65164e46-7f3d-3d98-ed04-9139998d46c1.png)
`The engine "node" is incompatible with this module. Expected version "^18.18.0 || >=20.0.0". Got "18.12.0"`
からわかるように、想定しているNode.jsと使用しているバージョンが異なるためエラーになっていました。

自身の環境で使用しているNode.jsのバージョンは`18.12.0`です。

ここで「別のNode.jsを入れる必要があるな」と思い`nvm`を導入することを決めました。

### nvmの導入
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

source ~/.bashrc

nvm install v18.20.2
```
`nvm`はNode.jsのバージョン管理ができるツールです。プロジェクトによってNode.jsのバージョンを使い分けたいとき、簡単にバージョンを切り替えることができます。
今回は`nvm`を入れて、Node.jsのv18で一番新しいものを入れました。

:::note warn
本来はここで既存のNode.jsをアンインストールして、まっさらな状態で`nvm`を導入するべきでした。それを怠ったため、今回の無駄な苦労が発生しました。
:::


### 依存関係のインストール（2回目）
これでNode.jsのバージョンが新しくなったので、行けるだろうと思って再実行しましたが、結果は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/05808442-89f5-358d-eb91-c1556b0427fe.png)

エラーメッセージが変わりません。
`Got "18.12.0"`
とあるように、使われているバージョンが変わっていないようでした。

### nvmでのバージョンの指定
`nvm`では`use`コマンドを使って使うバージョンを指定する必要があるらしいので、バージョンを以下の通り指定。
```bash
nvm use 18.20.2
```

### 依存関係のインストール（3回目）
3度目の正直ということで、三度`yarn`を実行しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/a96b7b8b-0094-e494-b4d9-707959b96299.png)
見事成功します。

:::note warn
後続の一連の失敗を考えると、なぜここで成功したのか今となっては不明です。
:::

### package.jsonの生成
ここもよくわからないポイントですが、一応やったことの記録として残っているので紹介します。

:::note info
`yarn create vite`した時点で`package.json`が作成されているはずなので、本来は生成不要
:::
```bash
yarn init
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/42622c00-5f12-45e1-20d1-4f333df4730d.png)

### モジュールの追加
これも今となってはなぜやったのかよくわかっていません。
どこかの環境構築のサイトを見様見真似でやった結果かと思います。

:::note info
依存関係のインストールの時点で必要なものが諸々入っているはずなので、本来このモジュール追加は不要
:::
```bash
yarn add vite typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint --dev
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/84353cb1-ef88-3d6d-8534-58caaaeec6bd.png)

結果、はじめに行った依存関係のインストールと同じエラーが出てパニックになりました。
先ほどから設定を変えていなはずなのに、同じエラーがでてしまったからです。
（今思えば、自分自身がワケのわからないオペレーションをしているのが悪いのですが…）

ここでは、`nvm`を使用してバージョンを`18.20.2`に変えたはずなのに、エラーメッセージ上では`18.12.0`が使われていることになっており、大パニックでした。
`node -v`コマンドや、`nvm current`コマンドでバージョンを確認しても、`18.20.2`が出てくるので、一体どこの設定が悪くて`18.12.0`がゾンビのように蘇ってきているのか不思議でなりませんでした。

:::note warn
冒頭に述べた通り、正解は`nvm`ではなく`vault`が導入されており、そちらでは`18.12.0`のままだったことが原因です。
（そうなると、なぜ`yarn`がうまく行ったのか説明がつきませんが…）
:::

### 再度原因の分析
* `nvm`でバージョン管理をするには、同じフォルダ内で`.nvmrc`というファイルを作成し、そちらにバージョンを記載する必要があること
* `yarn`のキャッシュが残っている可能性があるため、`yarn cache clean`でキャッシュを消す必要がある
* `package.json`で`engine`のプロパティを設定したほうがよい

など、様々な情報が出てきたので片っ端から試しましたが、いずれを試してもうまくいかずここまででほぼ丸一日時間を費やしていました。

### Node.jsをアンインストールする？
そんな折、そもそも元からあったNode.jsを消さずに`nvm`を導入したからだめなのでは、という閃きを得ます。

そこで、以下のサイトを参考にNode.jsのアンインストールを試みます。
https://blog.proglus.jp/5518/

#### パッケージ版でインストールしている場合
以下のコマンドでバージョンが表示されていれば、パッケージ版でインストールしていることになるそうです。
```bash
/usr/local/bin/node -v
```
しかし、結果は以下の通りでした。
```bash
zsh: no such file or directory: /usr/local/bin/node
```
そんなファイルやディレクトリがない、とのことだったので私のNode.jsはパッケージ版ではないことがわかりました。

#### homebrewでインストールしている場合
```bash
brew list node

No such keg: /opt/homebrew/Cellar/node
```
上記コマンドで一覧が表示されれば、homebrewでインストールされていることになりますが、エラーメッセージの通り、私の場合は違いました。

#### nodebrewでインストールしている場合
```bash
nodebrew -v

zsh: command not found: nodebrew
```
こちらもバージョンが表示されず、完全に露頭に迷いました。
この時点での私は万策尽きた状態で、絶望していました。

### Node.jsよ、どこにいる
絶望のさなか、ネットを彷徨っていると、どこのサイトかは記録を残していなかったのですが、Node.jsがどこにいるのかを確認できるコマンドがありました。
```bash
which node
```

実行結果は以下のとおりです。
```bash
/Users/{ユーザー名}/.volta/bin/node
```

どうやら、`volta`というのが鍵なようです。
調べてみると、これもNode.jsのバージョン管理用ツールのようでした

全く導入した記憶がなかったのですが、私が4月に行った環境構築で自ら残した手順の証跡をたどると確実に自身の手でインストールしていました。
恐ろしいですね。

## まとめ
今回は全く他人には参考にならない自分の失敗をまとめてみました。
あまりネット上には失敗の軌跡が残されていないように思ったので、恥ずかしながらこんな愚かな失敗をしている人もいるのだ、という戒めの意味を込めて記録として残しておきます。

学びとしては環境構築の手順の際、その手順はなんのためにやっているのか、を確実に理解しながらやることが肝要だということです。

ただやみくもに右から左にやるのではなく、意味を考えることで詰まったときのリカバリも容易になるのでは、と思いました。