📗 Node.jsバージョン管理ツール「fnm」のインストール方法と使い方

https://github.com/Schniz/fnm

🚀 **fnm（Fast Node Manager）** はWindowsユーザの方に一番おすすめなNode.jsのバージョン管理ツールです。

Windowsでは少々インストール作業が細かいので、実際の使い方も含めてこちらにまとめておきます。
なお、どんなツールも[**公式のREADME.md**](https://github.com/Schniz/fnm/blob/master/README.md)が最も信頼できる正しいドキュメントなので、そちらも併せてご覧ください🌟

:::note warn
別のツールからの乗り換えの際は、元のバージョン管理ツールをしっかりアンインストールしてください🙏
:::

**Node.jsのバージョン管理ツールがなんだかわからない方はこちら：**

https://qiita.com/heppokofrontend/items/1746c73a34d59b124013


**`fnm`のどこが魅力的なのかはこちら：**

https://qiita.com/heppokofrontend/items/5c4cc738c5239f4afe02?0

## 1. まずは`fnm`のインストール

**macOS/Linuxの場合**は次のコマンドをインストールして終了です。

```shell
curl -fsSL https://fnm.vercel.app/install | bash
```

### Windowsの場合

Chocolateyを利用します。
macOSで言うところのhomebrewなので、Windowsユーザの開発者の皆さんはぜひ導入しておきましょう💡

https://chocolatey.org/install

```shell
choco install fnm -y
```

続いて、プロファイルの設定です。

#### Windows PowerShell & PowerShell

PowerShellには2種類あります。
別途`pwsh`をインストールしている場合は、そちらも同じように設定します（以下、PowerShell）。

```powershell:Microsoft.PowerShell_profile.ps1
fnm env --use-on-cd | Out-String | Invoke-Expression
```

上記のコードを`Microsoft.PowerShell_profile.ps1`に記載してください。

このファイルの保存先は、PowerShellで`$profile`と入力することで確認できます。
その位置にファイルが存在しなければ作成します。

```powershell:例
$Profile
# > %HOMEPATH%/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1
```

:::note
**💡 Microsoft.PowerShell_profile.ps1 って？**
一派にプロファイルと呼ばれるもので、PowerShellが立ち上がるたびに実行されるものです。
:::

#### コマンドプロンプト

##### まず、ホームディレクトリに`.cmdrc.cmd`ファイルを作ります。

ホームディレクトリは`window + r`で「ファイル名を指定して実行」を開いたとき`%HOMEPATH%`と入力して開くディレクトリのことです。

そのディレクトリに`cmd`ファイルを作成してください。
ファイル名は何でもよいのですが、ここでは便宜上`.cmdrc.cmd`とします。

このファイルは先ほどのレジストリ操作により、コマンドプロンプトが起動するたびに必ず実行されます。
このファイルの中身を次のように記述[^1]して、作業は終了です。

[^1]: 2バイト文字を入力するときは、Shift_JISで保存しなければなりません。

```bat:.cmdrc.cmd
@ECHO OFF
REM Source: https://umi-uyura.hatenablog.com/entry/2021/09/30/083419

IF "%FNM_SETUP%"=="True" (
    EXIT /b
)

SET FNM_SETUP=True
FOR /f "tokens=*" %%z IN ('fnm env --use-on-cd') DO CALL %%z
```


##### 続いて、レジストリを操作します。

レジストリがよくわからない人は触らないに越したことが無いですが、次のコードをPowerShellに入力するだけでOKです。

```bat
reg add "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Command Processor" /v AutoRun /t "REG_SZ" /d "call c:%HOMEPATH%\.cmdrc.cmd" /f
```

上記の処理は、次の処理を行うものです。

1. 操作対象：`HKEY_CURRENT_USER\SOFTWARE\Microsoft\Command Processor`
2. 文字列値を増やします：`AutoRun`
3. 値を設定します：`call c:%HOMEPATH%\.cmdrc.cmd`

:::note warn
**プロファイルで`call`するファイルパスについて**
1つ前のセクションで作った`cmd`ファイルの名前を`.cmdrc.cmd`ではないものにした場合、`AutoRun`の値に指定するファイルパスを適宜調整してください。
:::


#### Git Bash（相性が悪そう）

※ Git Bashでは自動で切り替わらず、切り替えることもできないようです（PowerShell依存）（アドバイスお待ちしております）
※ `npm`や`yarn`コマンドが正しく動作しません
※ Git Bashで`echo $PATH`と入力して出てきた値をバックアップしておくと安心かもしれません
※ Windowsのシステム環境変数とGit Bashは同期が取れていないことに注意してください

まず、システム環境変数がWindowsと共通になっていないため、共通化します。
PowerShellで`$env:Path`と入力して出てきた値をすべてコピーしてください。

取得したパスを整形します。

```:before
# 例
C:\Program Files\PowerShell\7;C:\Python310\Scripts\;
```

1. `;`を`:`に置換
2. `\`を`/`に置換
3. `C:/`を`/c/`に置換

```:after
# 例
/c/Program Files/PowerShell/7:/c/Python310/Scripts/:
```

整形したパスを設定します。

```bash:%HOMEPATH%/.bash_profile
export PATH="ここにパス"
```

PowerShellでNode.jsのバージョンを切り替えます。

```shell:PowerShell
fnm use X.X.X
```

Git BashでもNode.jsのバージョンが変わってることを確認します。

```bash:GitBash
node -v
```

#### その他のシェル

[fnmのREADME.md](https://github.com/Schniz/fnm)を参照してください。


## 2. `fnm`でNode.jsをインストールする

ｖ16.13.0をインストールする場合…

```powershell
fnm install 16.13.0
```

インストールが終わったら、`use`で切り替えます。

```powershell
fnm use 16.13.0
node -v # > v16.13.0
npm -v  # > v8.1.0
```

これでnodeとnpmコマンドが使えるようになります。


## 3. 各プロジェクトに`.node-version`ファイルを設置する

`.node-version`または`.nvmrc`ファイルがあるディレクトリでは、自動的にNode.jsのバージョンが変化します。
指定されたバージョンがインストールされていないと、`fnm`が自分から「○○のバージョンがないけどインストールしていい？」って聞いてきてくれるので、特に意識せずに作業をすることができます。

プロジェクトのルートで`fnm use`を使って好きなNode.jsのバージョンに切り替えた後、次のコマンドで`.node-version`ファイルを生成してコミットしておきましょう🌟

```shell
node -v > .node-version
```

## 終わりに

macOSでは`n`推しですが、Windowsでは`fnm`が一押しです！
バージョン管理ツールを決めかねてる方はぜひ`fnm`を使ってみてはいかがでしょうか。

## 参考文献

- [Windows環境のgit bashに環境変数を追加する](https://qiita.com/n_otsuka/items/bfba784f37a98a930629)
- [WindowsのNode.jsバージョン管理をNodistからfnmに変えてみる](https://umi-uyura.hatenablog.com/entry/2021/09/30/083419)