fish-nvmだけ使ってたらenv: node: No such file or directoryと怒られた

気づくまで

fishシェル環境にするついでにnodebrew使うのをやめてnvmに移行した。nvmはそのままでは使えないので自分はfish-nvmを使っていた。

ふとしたときからVSCodeのGit連携機能が使えなくなってしまったり、ターミナルでwhich nodeとかやってもenv: node: No such file or directoryって言われるようになっているのに気づいた。

ググるとどうやらPATHに問題があるみたいな雰囲気があったけどPATHいじってないし困ってしまった。

原因

グローバルのNodeバイナリを消したせいだった

少し前にhomebrewで入れているyarnの挙動がおかしかったので一度アンインストールして再インストールしていた。Yarnは実はNodeを依存パッケージとして一緒にインストールするので、一緒にNodeもアンインストールした。

「nvmで管理するしグローバルNodeいらんやろ、ついでに消しとこ」

と思って消したのだった。

Yarnのインストールガイドには「nvmとか使うならNode一緒に入れなくていいから--without-nodeを使う」って書いてあるので、

$ brew install yarn --without-node

再インストール時にはこれでグローバルNodeバイナリはナシにしたのだった。

fish-nvmはセッション開始時にnvmのNodeバイナリを読み込まない

fishでnvmを素直に使うとターミナルの開始に1〜3秒位遅延が発生するらしい。だからfish-nvmという存在があってこいつがよしなにしてくれているのだけど、仕様として「セッション開始時にnvmの抱えてるNodeバイナリを読み込まない」っていう挙動をする。

シェルのこととnvmの設計に詳しくないのでなんでfishでnvm使うと遅くなるのかわからないけど、とにかくそういうことらしい(nvm側の問題らしい)。

グローバルのNodeが消失したせいでセッション開始時に読み込めるNodeがいなくなったので、そりゃ色々と動かなくなるわな……というはなしだった。

グローバルのNodeバイナリを消した途端色々壊れてしまったというか、いままでグローバルにNodeバイナリがいたから運良く動いていたとも言える……。

グローバルにNode入れ直した

homebrewでNodeバイナリ入れ直したらとりあえず直った。Nodeバイナリ入れると/usr/local/bin/nodeが入るので元通り。

シェル起動してwhich nodeした段階では/usr/local/bin/nodeが返ってきて、そのあとnode -vするとnvmのdefaultのnodeバージョンが返ってくる。もう1回which nodeすると/User/<username>/.nvm/versions/node/<version>/bin/nodeが返るように戻った。

fish-nvmのREADME

本件の回避策としては、そもそもfish-nvmを使わず遅延問題を代償してbassで直接nvmを毎セッションごとに起こすほうが書かれている。けど、Nodeのグローバル入れ直す前に自分の環境でこれやっても、結局bassの処理のほうがあとからされるので結局解決しなかった。(なぜなのか)

あとfish-nvmのREADMEに書かれているこの方法

Another common scenario is if you need to have the binary of the node or package available. For example if you are vim user, some plugins need access to the node binary. Since we only source nvm when we use one of the alias, you will probably get an error saying that node isn't available.

For example to create a binary for node we could create a file under /usr/local/bin

touch /usr/local/bin/node Open that file on your editor and paste the following:

! /usr/bin/env fish

__nvm_run "node" $argv Make that file executable:

chmod +x /usr/local/bin/node Test it

which node To simplify this process there's another helper function nvm_alias_command

If you run nvm_alias_command without any arguments it will create the alias binaries provided by default by fish-nvm: npm, node, npx, yarn

ここの部分も回避策の一種だと思うのだけど、なぜか自分の環境ではうまく動かなかった(なぜかシェルが起動しなくなった、なぜなのか)


fmnというnvmライクなfish専用のnodeのバージョンマネージャもある。fish1本でやっていくならこれでいいんだけど、自分は諸事情でzshbashも使うので、普段はfishだけどfmnに依存するのはベターではない……fish-nvmを使う必要がある。

なんだかスッキリ解決してないけど、とりあえずもとに戻ったのでヨシということにする(グローバルのNodeホントは捨てたい)