できない.dev

nvm でバージョンを切り替えるとグローバルインストールした npm パッケージが使えない

nvm はバージョンごとに独立した `lib/node_modules` を持つため、切り替えると前のバージョンのグローバルパッケージは PATH から外れる。
`nvm reinstall-packages` か `--reinstall-packages-from` で移送する。

公開:

要約

nvm use で Node.js を切り替えた途端に tsc: command not found のようになるのは、パッケージが消えたわけではありません。
nvm は バージョンごとに独立したグローバル領域 を持っており、切り替えると前のバージョンの lib/node_modules が PATH から外れるためです。

既にインストール済みのバージョン間で移送するなら、移送先を有効化してから nvm reinstall-packages を実行します。

nvm use 22.11.0
nvm reinstall-packages 20.11.0   # 20.11.0 のグローバルパッケージを 22.11.0 へ複製

新しいバージョンをこれから入れるなら、インストールと同時に移送できます。

nvm install --reinstall-packages-from=20 22

よくある原因

  1. グローバル領域がバージョンごとに分かれている: 実体は ~/.nvm/versions/node/<version>/lib/node_modules です。nvm which current でどの bin が使われているかを確認できます。
  2. 移送コマンドを打っていない: nvm install 22 は新しい Node を入れるだけで、旧バージョンのパッケージを引き継ぎません。
  3. ~/.npmrcprefix が残っている: 過去にグローバルインストール先を手動で変えていると、nvm の想定するパスと食い違います。
    公式 README も prefix 設定は nvm と非互換だと注意しています。
  4. システム Node と混同している: /usr/local/lib/node_modules に入れたパッケージは nvm の管理外です。nvm deactivate で PATH を戻すと切り分けられます。

解決策

1. インストール済みバージョン間で移送する

--reinstall-packages-fromnvm install に紐づいたオプションなので、既に入っているバージョン同士では使えません。
この場合は移送先を有効化してから nvm reinstall-packages を単体で実行します。

nvm ls                    # 移送元・移送先のバージョンを確認
nvm use 22.11.0           # 移送先を有効化
nvm reinstall-packages 20.11.0

なお 公式ドキュメント(新しいタブで開く) にあるとおり、この操作で npm 自体のバージョンは変わりません。

2. インストールと同時に移送する

これから新しいバージョンを入れるなら、1 コマンドで済みます。

nvm install --reinstall-packages-from=20 22
nvm install --reinstall-packages-from=current 'lts/*'   # 現在有効なバージョンから最新 LTS へ

npm も最新にしたい場合は --latest-npm を併用します。

3. .npmrc の prefix を確認する

npm config get prefix
grep -n 'prefix' ~/.npmrc 2>/dev/null

prefix~/.nvm/versions/node/... 以外を指していたら、その行を削除して新しいシェルを開き直します。

4. 何が欠けたのかを比較する

切り替え前後で一覧を取って差分を見ると、移送漏れがすぐ分かります。

npm ls -g --depth=0

出力に自分が使っている CLI(typescriptpnpm など)が含まれているかを確認してください。

この記事は役立ちましたか?