node.jsのバージョン管理のベストプラクティス?

Webサイト制作や開発には、欠かせないものとなったnode.js。
同時に複数のプロジェクトを進めていると、node.jsのバージョンを合わせることが求められます。
また、M1 Macでは古いv15までのバージョンは対応しておらず、Rosetta使ったり、pythonのバージョン違いなどいろいろと面倒があります。
なお、QiitaやらZennに同内容の記事はありますが、自分で纏めておくコトに意義を感じてます。

anyenvとは?

node.jsのバージョン管理のお話なんですが、nodenvだけを入れるより、断然anyenvで纏めて管理した方が良いので、anyenvから始めます。

anyenvは、phpやpythonなどのバージョン管理を行う、phpenvやpyenvなどを束ねるものです。nodenv、phpenv、pyenvなどを纏めて管理できるので便利です。

様々な言語を使って開発を行っている場合は、anyenvで管理するのがベストだと思います。
anyenvでは、以下の言語などの環境を管理できるようです。

nodenv、pyenv、Renv、swiftenv、crenv、denv、erlenv、exenv、goenv、hsenv、jenv、jlenv、luaenv、phpenv、plenv、rbenv、sbtenv、scalaenv、tfenv

https://github.com/anyenv/anyenv-install

M1 Macだと、従来の環境とpythonのバージョンが合わないため、node.jsで開発を行う場合でも、pyenvが必要になるケースもあります。やはり、anyenvで統合管理するのがベストじゃないでしょうか。

anyenvの導入と設定について

anyenvは前述の通り、様々なOSS言語のバージョン管理をまとめ上げる各種言語のパッケージマネージャー的なツールです。README.md通りですが一応紹介しておきます。

Homebrewが導入されている場合

macOSでは、Homebrewが入っていれば、以下コマンドで導入できます。

1. インストール

# Homebrewでanyenvインストール
brew install anyenv

# シェルを再起動
exec $SHELL -l

2. セットアップ

# anyenvを起動
anyenv init

# .zshrcにeval "$(anyenv init -)"を記述
echo 'eval "$(anyenv init -)"' >> ~/.zshrc

# インストールマニフェストディレクトリの初期化
anyenv install --init

マニュアルでgitリポジトリからインストールする場合

1. インストール

git clone https://github.com/anyenv/anyenv ~/.anyenv

2. セットアップ(Zshの場合)

# 環境変数にanyenvのパスを追加
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.zshrc

# anyenvを起動
~/.anyenv/bin/anyenv init

# インストールマニフェストディレクトリの初期化
anyenv install --init

anyenvコマンド一覧

インストールした**envに関する情報を、anyenvコマンドで様々に表示できます。

コマンド内容・説明
% anyenvヘルプ、anyenvのバージョン確認など
% anyenv global**envごとのグローバルバージョンの表示
% anyenv local**envごとのローカルバージョン表示
% anyenv envsインストール済み**envの一覧
% anyenv install -lインストールできる**envの一覧
% anyenv install **env**envのインストール
% anyenv uninstall **env**envのアンインストール
% anyenv version**envごとのグローバルバージョンとインストールパスを表示
% anyenv versions**envごとにインストールされているバージョンを表示
% anyenv rootanyenvのルートディレクトリパス表示

anyenvプラグインのインストール

プラグインを導入するディレクトリを作成します。

# anyenvのプラグインディレクトリ作成
mkdir -p $(anyenv root)/plugins

anyenv-update

**envを一括でアップデートできます。

# gitからクローン
git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update

# アップデート
anyenv update

anyenv-git

全ての **env とインストールされたプラグインのディレクトリで git を実行することができます。

# gitからクローン
git clone https://github.com/znz/anyenv-git.git $(anyenv root)/plugins/anyenv-git

# アップデート
anyenv git pull

# ガベージコレクタ(メモリ解放)
anyenv git gc

# すべてのリモートリポジトリを表示
anyenv git remote -v

# ステータスを表示
anyenv git status

nodenvを導入

anyenvからnodenvを導入します。他の**envも手順はほぼ同様です。

# anyenvでnodenvをインストール
anyenv install nodenv

# シェルを再起動
exec $SHELL -l

# 動作確認(正しくインストールされていれば、バージョンやコマンド一覧が表示される)
nodenv

nodenvのプラグインを導入

プラグインをインストールするために、nodenvディレクリにフォルダを作成します。

# nodenvのプラグインディレクトリ作成
mkdir -p "$(nodenv root)"/plugins

rehash自動化プラグイン「nodenv-package-rehash」

node.jsをインストールしたり、npm install -gした際にnodenvに認識させるめに、「nodenv rehash」コマンドを実行する必要があります。このプラグインにより、rehashを自動化します。シェル初期化時の自動ハッシュ化を解除しておく必要あります。

# nodenv-package-rehashのインストール
git clone https://github.com/nodenv/nodenv-package-rehash.git "$(nodenv root)"/plugins/nodenv-package-rehash

# シェル初期化時のnodenvの自動ハッシュ化を解除
echo 'eval "$(nodenv init - --no-rehash)"' >> ~/.zshrc

.node-versionによるローカル環境指定

ディレクトリ毎に使用するnode.jsバージョンを指定できます。

以下のようにバージョンを記述しておくと、そのディレクトリでは記述したバージョンのnode.jsで実行されます。他の**envも同様です。pythonなら、.python-versionにバージョン記述し、ディレクトリ単位で管理ができます。

18.12.1

nodenvコマンド一覧

コマンド内容・説明
% nodenvヘルプ、nodenvのバージョン確認など
% nodenv version現在のディレクトリで使用できるnode.jsのバージョンを表示
% nodenv versionsnodenvでインストールされているnode.jsバージョンの一覧表示
% nodenv install -lインストール可能バージョン確認
% nodenv install 18.XX.Xインストール可能バージョンを確認した上で、
インストール可能なバージョンを指定してインストール
% nodenv uninstall 18.XX.x指定バージョンをアンインストール
% nodenv globalグローバルバージョンの表示
% nodenv global 18.XX.Xグローバルバージョンを18.XX.Xに指定
% nodenv localローカルバージョンの表示
% nodenv local 18.XX.Xローカルバージョンを18.XX.Xに指定

補足:Apple Silicon(arm)で旧バージョンのnode.jsを使用したい場合

v15までのnode.jsはarmに対応しておらず、Rosettaを利用してIntelコンソール状態で導入する必要があります。

標準ターミナルの場合

ターミナルの情報から、「Rosettaで開く」にチェック。

チェック後に、ターミナルを立ち上げ、以下コマンドでIntel版のnode.jsを導入。

nodenv install 15.14.0

導入後は、ターミナル.appの「Rosettaで開く」にチェックを外しても問題ないようです。

VS Codeのターミナルの場合

「.vscode/settings.json」に以下を記述することで、デフォルトがRosetta Zshに変更になります。

{
	"terminal.integrated.defaultProfile.osx": "zsh-rosetta",
	"terminal.integrated.profiles.osx": {
		"zsh-rosetta": {
			"path": "arch",
			"args": [
				"-x86_64",
				"zsh",
				"-l"
			],
			"overrideName": true
		}
	},
}

これで、v15以下のarmに対応していないIntel版のnode.jsがRosettaによりエミュレートされて動くようになります。