[npm & Bower] Node を Homebrew でインストールした場合でも npm をうまく利用したい(global install 編)

過去に断片的に調べて利用していたものの、色々と混乱したのであらためて再調査。

公式ドキュメントが詳しいため、通常は問題は起こらないのだと推測。

利用中につまずいた部分を中心に記す。

前提

タイトルの通り Node.jsHomebrew でインストールされている。

% node -v
v5.2.0
% npm -v
3.5.2

実体は下記に存在する。

% ls -l /usr/local/bin |grep 'npm@\|node@' |awk '{print $9,$10,$11}'
node@ -> ../Cellar/node/5.2.0/bin/node
npm@ -> /usr/local/lib/node_modules/npm/bin/npm-cli.js

global install

sudo 付きでインストールする。

% sudo npm install -g Package_name

/usr/local/lib 以下に node_modules がインストールされる。

% npm list -g --depth 0
/usr/local/lib
├── autoprefixer@6.1.2
├── bower@1.7.0
    :
├── npm@3.5.2
├── stylestats@6.0.0
└── trash@3.4.0

cli コマンドは /usr/local/bin 以下にシムリンクが作られている。

% ls -l /usr/local/bin |grep 'node_modules' |awk '{print $9,$10,$11}'
bower@ -> ../lib/node_modules/bower/bin/bower
    :
npm@ -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
stylestats@ -> ../lib/node_modules/stylestats/bin/cli.js

上記の内、autoprefixertrash については後述する。

global update

sudo 付きでアップデートする。

% sudo npm update -g

command not found 問題

グローバルにインストールしていた npm コマンドがアップデートによって利用できなくなる問題。

% trash foo.txt
zsh: command not found: trash

調べてみるとインストールするパッケージが変わっていたりしがち。
前述の例であれば trashautoprefixer が該当。
比較するとコマンドが存在しないことが分かる。

global uninstall

前述の問題を解消するために、例えば trash をインストールし直す。

% sudo npm uninstall -g trash
% sudo npm install -g trash-cli

ENOENT: no such file or directory 問題

以下のコマンドで状況を確認するとエラーが表示される。

% npm list -g --depth 0
/usr/local/lib
    :
├── stylestats@6.0.0
├──  error: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/trash/package.json
└── trash-cli@1.2.0
npm ERR! error in /usr/local/lib/node_modules/trash: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/trash/package.json'

該当するディレクトリを調べると、ディレクトリが空の状態で存在する。
削除するとエラーが消える。
/usr/local/bin のシンボリックリンクはキレイに消えていた。

% cd /usr/local/lib/node_modules
% sudo rm -rf trash
% npm list -g --depth 0
/usr/local/lib
├── bower@1.7.0
    :
├── stylestats@6.0.0
└── trash-cli@1.2.0

以前に Homebrew と /usr/local の権限の取り合い問題にもあたっていた。
どうもパーミッションの問題でディレクトリを消せなかったように見える(確証なし)。

Homebrew ユーザーは node_modules の場所を変更する

前述のパーミッションの問題も出てくるため、Homebrew ユーザーは node_modules の場所を変更しようぜということになる。

$HOME にディレクトリを作成して、そこに配置させる。
公式ドキュメントにも変更方法が記載されている。

~/.npmrc
prefix = ~/local/lib/node_modules

shell にもパスを通す。

~/.zshenv
# for npm
if [ -d $HOME/local/lib/node_modules/bin ]; then
    export PATH=$PATH:$HOME/local/lib/node_modules/bin
fi

あたらしい node_modules をインストールする

npm をあたらしい設定配下に再インストールする。
sudo は必要ない。

% which npm
/usr/local/bin/npm
% npm install -g npm bower
/Users/****/local/lib/node_modules/bin/npm -> /Users/****/local/lib/node_modules/lib/node_modules/npm/bin/npm-cli.js
/Users/****/local/lib/node_modules/lib
└─┬ npm@3.5.2
    :

以前の node_modules を削除する

/usr/local/lib 以下の node_modules を削除する。

% sudo rm -rf /usr/local/lib/node_modules

/usr/local/bin 以下のシムリンクを削除する。

% cd /usr/local/bin
% ls -al ./ |grep '../lib/node_modules' |awk '{gsub(/@/,"");print $9}' |xargs rm -i

確認

ログインし直した後に確認。

% which npm
/Users/****/local/lib/node_modules/bin/npm
% npm bin -g
/Users/****/local/lib/node_modules/bin
% npm list -g --depth 0
/Users/****/local/lib/node_modules/lib
├── bower@1.7.1
└── npm@3.5.2

結論

  • .npmrc に設定を追加し、node_modules のインストール場所を変える。
  • node_modules/bin に path を通す。

公式とあわせて、こちらが参考になった。

続きます。

補遺

なお Node.js は nodebrew でもインストールできる。

この場合、node_modules は ~/.nodebrew 以下に配置される。
そのため global install 時に sudo が必要なかったり、cli コマンドのパスも自動で通ったりするようだ。
nodebrew を使うと、このあたりの悩みがなくなりそうな気もする(未検証)。

npm command