anyenv + ndenv を試す
Node 11 へ更新したら mapbox/node-sqlite3 が動作しなくなった。#1063 によれば既に修正の準備はできているものの CI サービス AppVeyor が Node 11 対応していないので待ちとなっているらしい。
これまでも node-sqlite3 のように node-gyp を利用した npm で Node バージョン更新による問題に遭遇してきたが、概ね短期間で対応された。そのため Homebrew で Node を最新バージョンにしていたのだけど、今回は 2 週間を経ても未解決である。ちょうど直近で node-sqlite3 を業務利用する機会があるため、これは困る。
また自身も npm 開発することもあって、いつかは *env
系ツールで複数 Node バージョンを検証できなくてはなぁと思っていた。Current 以外の動作テストは Travis CI に丸投げしていたが、特定 Node バージョンで問題が起きた時は環境を切り替えて検証しなければならない。というわけで今回の問題を契機に anyenv + ndenv を試すことにした。
anyenv をインストールする
riywo/anyenv の手順に従い anyenv をインストール。まずは git clone
。HOME 直下に .anyenv
という名前で git clone
する。
$ git clone https://github.com/riywo/anyenv ~/.anyenv
次に anyenv へパスを通す。手順だと echo
でプロファイル末尾に出力しているが、既存の設定を確認してからにしたいので .bash_profile
を vi で開く。
$ cd
$ vi .bash_profile
内容を確認して問題なければ好みの位置 (export をまとめている箇所など) や末尾に以下を追記して保存する。
export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init -)"
その後、有効化。手順では exec $SHELL -l
になっている。今回は .bash_profile
を自身で編集したから source
コマンドで読み直した。これは単に手癖の話。
$ source .bash_profile
anyenv のインストール手順は Linux や macOS を想定しているようで Windows はどうするのだろう?と思ったが、現在は WSL があるからそちらでどうぞ、ということなのかもしれない。Windows 版のインストール手順をググって見つけた WSLでWindowsにLinux開発環境を構築する - Qiita では実際そうしている。
インストールに成功したことを確認するため、anyenv の提供する *env
を表示。
$ anyenv install -l
Available **envs:
Renv
crenv
denv
erlenv
exenv
goenv
hsenv
jenv
luaenv
ndenv
nenv
nodenv
phpenv
plenv
pyenv
rbenv
sbtenv
scalaenv
swiftenv
無事、成功したようだ。こうして見ると対応環境が多い。今回の対象となる Node 系だけでも ndenv、nenv、nodenv の 3 種類ある。これらを個別にインストールしたり設定するのは非常に面倒なので実にありがたい。
anyenv-update をインストールする
anyenv 管理下の *env
を更新するために便利なプラグイン znz/anyenv-update をインストールする。これは anyenv の README からリンクされているので公認と考えてよいだろう。
まずはインストール先となるディレクトリーを作成。anyenv の手順でパスを通してあるから、その配下に入れる。作成後、実際にディレクトリーが存在することを確認。
$ mkdir -p $(anyenv root)/plugins
$ ls $(anyenv root)
README.md bin completions envs libexec plugins share
anyenv-update をインストールして存在を確認。
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
$ ls $(anyenv root)/plugins
anyenv-update
これを入れると
$ anyenv update
により *env
をまとめて更新できる。
Homebrew 管理下 Node を削除する
まずはグローバルな npm を確認。必要なら ndenv
に移行した後で入れ直すため、名前を控えておくこと。
$ npm ls -g --depth=0
/usr/local/lib
├── asar@0.14.3
├── eslint@5.3.0
├── eslint-config-standard@11.0.0
├── eslint-config-standard-react@6.0.0
├── eslint-plugin-import@2.13.0
├── eslint-plugin-node@7.0.1
├── eslint-plugin-promise@3.8.0
├── eslint-plugin-react@7.10.0
├── eslint-plugin-standard@3.1.0
├── npm@6.4.1
└── npm-check-updates@2.14.2
次にこれらをまとめてアンインストール。その後に npm が残っていないことを確認。
$ npm uninstall npm -g
removed 387 packages in 6.033s
$ npm ls -g --depth=0
-bash: /usr/local/bin/npm: No such file or directory
Node 本体をアンインストール。その後にバージョン表示コマンドを実行して失敗 = Node 消滅を確認。
$ brew uninstall node
Uninstalling /usr/local/Cellar/node/11.1.0... (3,936 files, 47.0MB)
$ node -v
-bash: node: command not found
Homebrew 環境が壊れていないことを確認。
$ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!
Warning: Broken symlinks were found. Remove them with `brew prune`:
/usr/local/share/man/man5/package-lock.json.5
/usr/local/share/man/man7/removing-npm.7
/usr/local/share/man/man7/semver.7
依存関係の警告が出ているので brew prune
を実行、回復したことを確認。
$ brew prune
Pruned 3 symbolic links and 10 directories from /usr/local
$ brew doctor
Your system is ready to brew.
これで Homebrew 管理下 Node を削除できた。もし which node
して残骸があるようなら rm
コマンドなどを実行して消す。私の環境では検出されなかったから、これで終わり。
ndenv をインストールする
anyenv 経由で ndenv をインストールする。実行してみて気づいたのだが anyenv install XXXX
だけでは ndenv がコマンドとして認識されず exec $SHELL -l
によるシェル再起動が必要だった。
インストール後、バージョン表示して存在を確認。
$ anyenv install ndenv
$ exec $SHELL -l
$ ndenv -v
ndenv 0.4.0-4-ga339097
ndenv の提供する Node バージョンを確認。Node だけでなく io.js も管理されている。
$ ndenv install -l
Available versions:
...前略
v10.12.0
v10.13.0
v11.0.0
v11.1.0
iojs-v1.0.0
後略...
Node バージョン管理
ndenv を用意したので
- グローバルを最新となる Node 11
- node-sqlite3 を必要とするプロジェクトでは Node 10
という環境を構築してみる。まずは各バージョンの最新版を入れる。インストール後には ndenv rehash
を実行する必要あり。
$ ndenv install v11.1.0
$ ndenv install v10.13.0
$ ndenv rehash
Node 11 をグローバルに設定してから Node と npm のバージョンを確認。
$ ndenv global v11.1.0
$ node -v
v11.1.0
$ npm -v
6.4.1
成功。ndenv では Node と npm を一緒にインストールしてくれる。
試しに簡単なプログラムを実行したり、既存プロジェクトで npm test
を起動するなどしてみたところ正常に動作することを確認できた。
次は特定のプロジェクトだけ Node 10 を有効化してみる。対象となる Node プロジェクトに移動してから以下を実行。その後にバージョン確認してみる。
$ ndenv local v10.13.0
$ node -v
v10.13.0
おお、無事に Node 10 が適用されている。すごい。
ndenv help local
の解説を読むと .node-version
というファイルを作成して ndenv はそこに記述された Node バージョンへ切り替えているとのことだった。設定がファイルになっているため、これをリポジトリーで共有すれば ndenv を利用するユーザー間で Node バージョンを固定することも可能。よい仕組みだ。
実際、node-sqlite3 を利用している既存プロジェクトを Node 10 に固定し、正常に動作することも確認できた。
まとめ
anyenv + ndenv で自由に Node バージョンを制御できる環境を手に入れた。契機となる node-sqlite3 互換問題も解決したので満足度が高い。今回は ndenv を試したが、他の言語による開発でも役立つだろう。