boring stuff

nvmでNode.jsのバージョンを自動切替

NvmNodeJavascript

emmdee@colus.img

プロジェクトごとにバージョンを固定する

そのプロジェクトで使用するNode.jsのバージョン番号だけを書いたテキストファイルを.nvmrcという名前でプロジェクトルートに置く。

.nvmrc
10.15.1

プロジェクトのディレクトリ内で$ nvm useと打つと階層を上にたどって.nvmrcファイルを見つけ出し、そのバージョンに切り替えてくれる。
これだけでも十分便利だが、意外とコマンドを打つのを忘れることが多い。

バージョンを自動で切り替える

nvm公式のGitHubページに「Deeper Shell Integration」というシェルスクリプトが紹介されている。.bashrcに追記すると、cdでディレクトリを移動するたびに.nvmrcファイルを探し、バージョンを自動で切り替えてくれるというものだ。

早速、bash版のシェルスクリプトを使ってみた。しかし、cdするとエラーでシェルが終了してしまう。環境依存のレアケースなのか、検索してもそれらしい答えは見つからなかったが、下記ページにヒントがあった。

cdの前にバックスラッシュを入れないとaliasで呼び出した時に無限ループをするので、必ずバックスラッシュ を付けてください

ということで、公式シェルスクリプトBash版の10行目、cd "$@";\cd "$@";と修正すると無事動作した。

起動時にも動作させる

このスクリプトはcdコマンドでのディレクトリ移動に伴ってバージョンを自動で切り替える動作を行うものだ。そのため、VS Codeのターミナルのように最初からプロジェクトルートで起動する場合は、起動後にcdコマンドを使わないため動作しない。
そこで、このスクリプトからcd以外の部分を切り出し、ターミナルの起動時にも自動でバージョンを変更するよう修正した。 下記がその修正版。
これでストレスなくプロジェクトごとにnodeのバージョンが自動で切り替わるようになった。

$HOME/.bashrc
find-up () {
    path=$(pwd)
    while [[ "$path" != "" && ! -e "$path/$1" ]]; do
        path=${path%/*}
    done
    echo "$path"
}

nvmuse(){    nvm_path=$(find-up .nvmrc | tr -d '[:space:]')    # If there are no .nvmrc file, use the default nvm version    if [[ ! $nvm_path = *[^[:space:]]* ]]; then        declare default_version;        default_version=$(nvm version default);        # If there is no default version, set it to `node`        # This will use the latest version on your machine        if [[ $default_version == "N/A" ]]; then            nvm alias default node;            default_version=$(nvm version default);        fi        # If the current version is not the default version, set it to use the default version        if [[ $(nvm current) != "$default_version" ]]; then            nvm use default;        fi        elif [[ -s $nvm_path/.nvmrc && -r $nvm_path/.nvmrc ]]; then        declare nvm_version        nvm_version=$(<"$nvm_path"/.nvmrc)        declare locally_resolved_nvm_version        # `nvm ls` will check all locally-available versions        # If there are multiple matching versions, take the latest one        # Remove the `->` and `*` characters and spaces        # `locally_resolved_nvm_version` will be `N/A` if no local versions are found        locally_resolved_nvm_version=$(nvm ls --no-colors "$nvm_version" | tail -1 | tr -d '\->*' | tr -d '[:space:]')        # If it is not already installed, install it        # `nvm install` will implicitly use the newly-installed version        if [[ "$locally_resolved_nvm_version" == "N/A" ]]; then            nvm install "$nvm_version";        elif [[ $(nvm current) != "$locally_resolved_nvm_version" ]]; then            nvm use "$nvm_version";        fi    fi}
cdnvm(){    \cd "$@";    nvmuse;}
alias cd='cdnvm'
nvmuse