Help us understand the problem. What is going on with this article?

Node.js グローバルインストールでハマった

More than 1 year has passed since last update.

簡単にいうとNode.js グローバルインストールにハマりました。いわゆるパスを通すのに苦労した話です。

tl:dr

Node.jsでグローバルインストールしたモジュールが実行環境によって参照できない時の調査ポイント

  • npm root -g で、モジュールのパスを確認
  • NODE_PATH にモジュールのパスを追加
  • VSCode の場合は.vscode/launch.json に NODE_PATH を追加

問題 グローバルインストールしたモジュールが読み込めない

グローバルインストール

shell
npm i -g 3rd_party_module

呼び出しするも失敗

index.js
const a = require('3rd_party_module')
// 読み込みに失敗する
// 🚨Error: Cannot find module '3rd_party_module'

解決方法

$NODE_PATHにグローバルインストールされたモジュールのパスを通せば良い。
グローバルインストールのパスがNode.jsのrequire()メソッドから参照されるためには、そのパスがglobal.module.pathsに入っている必要がある。まずはそれを確認する。

shell
$ node
> global.module.paths
[ '/opt/jarvis/repl/node_modules',
  '/opt/jarvis/node_modules',
  '/opt/node_modules',
  '/node_modules',
  '/root/.node_modules',
  '/root/.node_libraries',
  '/usr/lib/node' ]
> .exit # node を終了

次にグローバルインストールされたモジュールのパスを確認する。

# モジュールがグローバルインストールされているパス確認
$ npm root -g
/usr/local/lib/node_modules

global.module.pathsに入っていないので、追加する。そうするには$NODE_PATHという環境変数に追加する。

shell
$ NODE_PATH="npm root -g"
# 確認
$ node 
> global.module.paths
[ '/usr/lib/node_modules/repl/node_modules', 
  '/usr/lib/node_modules', 🌟追加されている
  '/usr/node_modules',
# ・・・以下略

Dockerを使う場合は、このパスをDockerfileに定義する。

ENV NODE_PATH /usr/lib/node_modules

Mac でパスが通らない

Docker はうまくいったものの Mac でグローバルインストールしたモジュールが参照できない。

.bash_profile
NODE_PATH="npm root -g"
export NODE_PATH

❌ NODE_PATH = npm root -g となってしまうためNG. ダブルクォーテーションだとダメ。

.bash_profile
NODE_PATH=`npm root -g`
export NODE_PATH

NODE_PATH = /usr/local/... (npm root -gの結果が代入される) が入るようになった。以下のコマンドで環境変数を反映。

shell
source ~/.bash_profile
echo $NODE_PATH 
/usr/local/... # O.K. 

コンソールから、Node.jsを実行してみたらちゃんとグローバルインストールされたモジュールが読み込まれていた。

VSCode でパスが通らない

しかし、VS Codeから実行すると、グローバルインストールしたモジュールが読み込まれない...。色々調べたら、launch.json に 環境変数追加してやればいいみたい。

.vscode/launch.json
 ~~~~~ 中略 ~~~~~
  {
    "type": "node",
    "request": "launch",
    "name": "VSCodeでのデバッグ",
    "program": "${workspaceFolder}/nodejsproject/index_from_vscode.js",
    "env": {
        "NODE_PATH": "/usr/local/lib/node_modules" 🌟 ここ!
    }
  }
 ~~~~~ 中略 ~~~~~

いくつか変数っぽいのは使えるのかな〜と思って、"${npm root -g}" を設定してみたけど"npm root -g"がNODE_PATHとして設定されるだけだったので仕方なく直打ちです。

余談

そもそもグローバルインストールするのは良くないとか議論があるのだけど、たくさんのNode.jsプロジェクトがあって共通ライブラリ的に使用したいときは使うよね?でも、package.jsonに依存関係残らないから、困る。Dockerfileに記述するだろうから大丈夫だとは思うけどみんなどうしてるだろう。気になる。

shintarogit-on-qiita
モバイルアプリケーションエンジニア。iOSとAndroid。しかし自分のスマホはiPhoneなのでそっちやりたい。AWSやNode.js、Vue.jsもやる。なんかサービス作るとかならわりと好き嫌いなくやる。やる。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした