VM開発が捗る! node_modulesは好きなところに移動させて使おう!
目次
こんにちは。
開発チームのワイルド担当、まんだいです。
Node.jsでシステムを開発しないとしても、Node.jsを使って作業負担は減らすとかっていうパターンはよくあると思います。
例えば、webpackを使ってCSSのプリコンパイルやJSファイルのトランスパイルはするとか、定形作業はgulpでスクリプトを組んで定期実行しているとか、利用ケースは色々あって着実に生活に馴染んできているなという気はしています。
そんなNode.jsのパッケージ管理ツールとしてnpmというのがありますが、今回はとある理由でnode_modulesディレクトリをプロジェクトディレクトリ外に移動しなくてはいけなくなった、そんな時の対処法をまとめました。
とある理由ってなんだ?!
とある理由とは、開発環境の問題です。
開発環境としてVMというのはよく使われていると思いますが、今回はWindows10がホストOSで、VirtualboxでCentOS7を動かしている(そしてそれをvagrantで管理)といったVMを使った開発環境としてはよくある形です。
そんなよくある開発環境に、思わぬ落とし穴がありました。
唐突ですが、私のこだわりポイントとして、開発する時は必ずVisualStudioCode(以下、VSCode)で、というのが今年こだわっていこうかと思っているポイントで、もう今年も8月、だいぶ手に馴染んできました。
VSCodeはNode.js(TypeScript)で開発されていて、Electronを使ってマルチプラットフォームで利用できるエディタになっています。
なっていますが!
VSCodeのショートカットキーがLinux版ではなかなか使いにくいので、VM上にVSCodeをインストールしてそれで開発する、といった選択肢はありません。それはもはやストレスでしかないのです(Windows版の半端じゃない使いやすさはきっとマイクロソフトが開発してるからですね)。
よって、開発環境の構成もVSCodeを軸に一捻りする必要があります。
結論から言うと、VirtualBoxの共有フォルダ機能でプロジェクトディレクトリを丸ごと共有することで、WindowsのVSCodeで編集した内容をVMと共有している、ただそれだけです。
VMもヘッドレスモードで起動すれば、思いの外負荷も抑えられるのでVM3台くらいまでならいけますね。
落とし穴その1 「node_modulesディレクトリは共有できない」
状況をお分かりいただいたと仮定して、大きな問題は残ります。
それが「node_modulesディレクトリは共有できない」という問題。
ファイル的には共有できていますが、よくよく考えると、npm install した時点のプラットフォームでnode_modulesは作られるため、プラットフォーム依存のバイナリを内包するモジュールなんかで不具合が出ます。
node_modulesをプロジェクトディレクトリ外に置ければ、この問題は解決できそうです。
その代わり、開発プラットフォーム毎にnpm install する必要が出てきますが、npm install ってそういうものかなと思っているのであまり気にしていません。
落とし穴その2 「Maximum call stack size exceeded」
共有フォルダ内でnpm install すると、「Maximum call stack size exceeded」というエラーによく出くわします。
あまり良くわかってなかったのですが、このエラーの原因が共有フォルダにあるということのようです。 参考文献 - npm ERR! code ETXTBSY · Issue #9979 · npm/npm · GitHub
なので、この問題もnode_modulesをプロジェクトディレクトリ外に置けば解決しそうです。
node_modulesを好きなところにインストール
実はnpm configコマンドでnode_modulesの位置を変えることができます。
以下のコマンドで変更可能です。
npm config set prefix "/home/vagrant"
これでnpmが認識するnode_modulesディレクトリは「/home/vagrant/node_modules」になりました。
ただ、これだけではnpmがnode_modulesのある位置を「/home/vagrant/node_modules」と認識するようになったというだけなので、この状態でnpm install しても、やっぱりpackage.jsonと同階層にnode_modulesが。しつこいぜ・・・。
なので、インストールコマンドにもプレフィックスを指定してあげて、以下のコマンドでインストールすることになります。
npm install --prefix "/home/vagrant"
こうすると、エラーが出ます、多分。
こういうエラー。
npm WARN saveError ENOENT: no such file or directory, open '/home/vagrant/package.json'
package.jsonがない! あるよ!
と思ったら、--prefixで指定したディレクトリにpackage.jsonが必要なんですね!
ハードコピーすると管理が大変なので、シンボリックリンクで対応します。
cd /home/vagrant ln -s /home/vagrant/src/package.json ln -s /home/vagrant/src/package-lock.json # ある時
package-lock.jsonはあれば、という話ですが、初回インストールの場合は、逆にオリジナルが「/home/vagrant」に存在することになるのでインストールが終わったらワーキングディレクトリにコピるといった謎の作業が発生します。
これもVSCodeのため。致し方ない。
後はプレフィックス付きのnpm install を実行すればインストールが進みます。
余談ですが、npm install がやたら遅いなと思ってましたが、共有フォルダ外で実行すると「あっちゅーま」に終わってしまいました。
共有フォルダって便利ですが遅いんですね。
どこでもいいって訳でもない時がある
どこでもインストールできると言った割には、どこでもいい訳でもないと。
以下はとあるディレクトリにnode_modulesをインストールし、タスクランナーのgulpを実行した時のことです。
gulp sass [06:46:05] Local gulp not found in ~/src [06:46:05] Try running: npm install gulp
グローバル、ローカルともにgulpをインストールしているのは確実なので、おかしいのはnode_modulesがpackage.jsonと同階層にないからなんだと思います。
少しググっても分かりそうになかったので、gulpのソースを覗いてみるとなんとなく分かりました。 → gulp-cli/index.js at master · gulpjs/gulp-cli · GitHub
cfgLoadOrder配列に入っている文字列はhomeとcwdだけなので、ホームディレクトリ直下にnode_modulesを持ってくれば良さそうです。
サンプルで貼ったコマンドのプレフィックスがホームディレクトリになっているのはそういうところが理由です。
ホームディレクトリ配下にnode_modulesを作成した場合、いつもの場所にnode_modulesがなくとも正常にgulpのタスクが実行できました。
なんとなくコンフィグファイルを書けば自由度が上がりそうな気もするんですが、こちらはよくわからなかったので時間があれば調べてみます。
まとめ
色々と脱線したりして、文章がとっ散らかってしまったので、まとめます。
- npm install したディレクトリはVMの共有フォルダでは共有できないケースがある
- プラットフォーム依存のバイナリを必要とするモジュールを使っているとNG
- 共有フォルダの性質上、共有フォルダ上ではnpm install すらできない
- ホストとゲストが *nix系なら、もしかするとOK?
- node_modulesの作成位置は、npm install コマンドのオプション、「--prefix」で変更することができる
- 「--prefix」で指定するディレクトリには、予めpackage.jsonを仕込んでおく必要がある(シンボリックリンクでもOK)
- gulpなど、node_modulesの位置が自由にならない時もある
- node.jsは便利
結局ホームディレクトリ直下がいいかなぁと思っています。
VMはプロジェクト毎に別々のものを使いますし、コンフィグファイルでなんとかできても、自分のためだけに gitignore するのもなんか違うなぁと思ったり。
node_modulesが作業ディレクトリから分離できて、ひとまず何よりでした。
以上です。