「Nodist」でNode.jsのバージョンを管理する(+Gulpのエラー対処)

Gulpを使ってみたのをきっかけに、静的ページの構築にはGulpをはじめNode.jsのパッケージ(Nunjucks, SASS…)を活用するようになりました。

導入開始時はメンバーがほぼ同時に環境構築しそれに合わせてGulpのタスクを整えていたので特につまづくことはありませんでしたが、後から参加したメンバーが最新バージョンのNode.jsで環境構築したとき、他メンバーの環境とは相性が合わずエラーが出るケースをよく見るようになってきています。

そんなNode.jsのバージョン問題をクリアするために「 Nodist 」を入れる方向に向かっているので、その方法を紹介します。 (環境はWindowsです)

Nodistの導入方法

準備:本家のNode.jsをアンインストール

既に本家からインストールしたNode.jsを使っている場合は、まずアンインストールしてください。
※ 注:後々Nodist経由でインストールするバージョンを指定するので、自分が今どのバージョンを使っているかは必ず控えておきましょう。

コントロールパネルの【プログラム>プログラムと機能】から「プログラムのアンインストール」を開き、Node.jsをアンインストールします。

Node.jsのアンインストール

STEP1:Nodistをインストール

Nodistのインストールを進めます。配布ページは下記。
https://github.com/nullivex/nodist/releases

Nodistのインストール

当記事執筆時点の最新バージョンは v0.9.1 でした。
「nodistSetup-v0.9.1.exe」をクリックしてダウンロード後、インストーラーに従ってインストールを進めます。
完了後、次のコマンドを打ってNodistのバージョン情報が返ってくればOKです。

$ nodist -v

STEP2:使いたいバージョンをインストール

次のコマンドで、使いたいNode.jsのバージョンを登録していきます。

$ nodist + {バージョン}

インストール可能なバージョンが知りたいときは次のコマンドで一覧が表示できます。

$ nodist dist

既に自分がインストールしてあるバージョンの一覧を表示するコマンドは次です。

$ nodist list
# 結果例
  (x64)
  8.16.1
> 11.15.0  (global: 11.15.0)
  12.10.0

上の例では、 先頭に > がついている v11.15.0 が、現在有効になっているバージョンであることを指しています。また (global: 11.15.0) の表記のとおり v11.15.0がグローバルのバージョンとなっている ことがわかります。

バージョンの切り替えは次のコマンドで実施できます。

$ nodist {バージョン}

STEP3:ディレクトリ単位で使いたいバージョン(ローカルバージョン)を指定する

STEP2までで、コマンド1つでNode.jsのバージョン切り替えができるようになりました。
これだけでも十分便利そうですが、複数のプロジェクトを持っている場合はプロジェクトディレクトリに移動( cdコマンド )した時点で適したバージョンに切り替わるようになっているとありがたいです。

対象のディレクトリに移動し、nodist localを実行します。

$ cd {ディレクトリへのパス}
$ nodist local {バージョン}

完了後、移動したディレクトリの直下に .node-version というファイルが作成されます。
中身はバージョンが書いてあるだけのごくシンプルなものなので、自分でこの.node-versionファイルを作成してもOKです。

.node-version

ここまで実施するとnodist listの結果が少し変わります。
下記は グローバルをv11系、ローカルをv12系 に固定したときのコマンド実行結果の例です。

$ nodist list
# 結果例
  (x64)
  8.16.1
  11.15.0  (global: 11.15.0)
> 12.10.0  ({ディレクトリへのパス}.node-version: 12.10.0)

({ディレクトリへのパス}.node-version: 12.10.0)という表記が加わりました。
きちんと.node-versionが参照されていることがうかがえ、先頭の>マークも意図した位置にありますね。

このように、ディレクトリ毎に適した.node-versionを作っていくことで、そのディレクトリに移動するだけでバージョンの切り替えができます。
Nodist側の準備はこれで完了です。

はじめは最新バージョンのNode.jsに合わせて使用するモジュールやgulpfile.jsをアップデートしていく方針も考えていましたが、運用プロジェクト全てに都度適用していくのは現実的ではないため「構築開始時に使ったバージョンに固定する」方針に落ち着いています。

Gulpが起動できない?

グランフェアズでは、Node.jsを主にタスクランナー(Gulp)を動かす目的で使っています。
例えば初期化までのコマンドフローはこんな流れでした。

$ cd {ディレクトリへのパス}
# 環境を初期化(package.jsonをもとに、Gulpなどのモジュールをローカルインストール)
$ npm install
# ファイルを初期化(必要なファイルをローカルに生成)
$ npx gulp init

しかしNodistの準備完了後、cdで移動した時点でnodist listの実行結果はバッチリ意図どおり。でもいつも通りGulpを実行しようとするとエラーが出るというケースがありました。

結論としては、npxコマンドを使うと.node-versionによって指定されるローカルバージョンが使われず、グローバルバージョンが優先される のが原因であることがわかったので、対処法を2つご紹介します。

対処法1:グローバル&ローカル両バージョンを一致させる

ローカルで使いたいバージョンに合わせてグローバルのバージョンを都度変更する方法です。

$ cd {ディレクトリへのパス}
# グローバルとローカルそれぞれのバージョンを確認
$ nodist list
# 不一致だったら、ローカルに合わせてグローバルのバージョンを切り替える
$ nodist {ローカルのバージョン}
# 以降、任意のコマンドを実施
$ npm install
$ npx gulp init

「ディレクトリに移動するだけでバージョン切り替え完了」とはいかなくなりますが、変わらずnpxコマンドが使える方法です。

対処法2:npxコマンドを使わない

npxではなく、npmの「run-script」という仕組みをつかってGulpを実行できるようにします。
package.jsonを開き、"scripts":{}部分に次のように指定を追加します。

{
  "scripts": {
    "{run-script名}": "{npxでのコマンド}",
    "gulpinit": "gulp init"
  }
}

これにより、従来のnpx {npxでのコマンド}と、npm run {run-script名}、2つのコマンドがどちらも同じ処理を返すようになります。
これまでのコマンドnpx gulp initを、以降はnpm run gulpinitに置き換えます。

$ cd {ディレクトリへのパス}
# 以降、任意のコマンドを実施
$ npm install
$ npm run gulpinit

私はディレクトリ移動で切り替わることを優先したかったので対処法2派です。

※ 余談
対処法2を採用したところ、継続的にファイルを監視するようなタスクを実行したときにCtrl+Cで停止ができなくなる事象がありました。何かしらエラーを吐かせて強制終了することで凌ぎましたが、そこで時間が食われてしまうようなら対処法1を採用したほうが無難です。
しかし、別のPCで同じように環境を作ったときはそういった問題はなく、調べても前例が見当たらない状況…。ここだけスッキリしていませんが他に共感できる方がいたらと思い、そっと書いておきます。


見てのとおり、Nodistの導入よりも移行後の対処に苦戦しました…。総じてNode.jsまわりの世界観はやっぱり難しい。

とはいえNodist自体はとてもシンプルなツールなので、Node.jsのバージョン違いによるトラブルでお困りの場合は思い切って移行してみるのがオススメです。
万一スムーズに移行できなかったり急用が入ってもすぐ元の環境に戻せるよう、必ず使用中のバージョンを控えたうえでお試しください。