npm 経由で scripts のコマンドを実行すると $(npm bin) が PATH に追加されるらしい

package.json の scripts のところには $(npm bin)/mocha のようにローカルの mocha を明示的に指定しないといけないのかと思いきや、$(npm bin) が勝手に PATH に追加されるみたいです。
なので、mocha と記述するだけでローカルに mocha が存在すればそちらが使われます。

実際に $PATH の値を見てみます。

% cd /tmp/
% npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (tmp)
version: (0.0.0)
description:
entry point: (index.js)
test command: echo $PATH
git repository:
keywords:
author:
license: (ISC)
About to write to /private/tmp/package.json:

{
  "name": "tmp",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo $PATH"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) yes
% npm test | sed "s|$HOME|\$HOME|g"

> tmp@0.0.0 test /private/tmp
> echo $PATH

/usr/local/Cellar/node/0.10.24/lib/node_modules/npm/bin/node-gyp-bin:/private/tmp/node_modules/.bin:/usr/local/Cellar/node/0.10.24/bin:$HOME/.rbenv/shims:$HOME/local/bin:/usr/local/share/npm/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
% echo $PATH | sed "s|$HOME|\$HOME|g"
$HOME/.rbenv/shims:$HOME/local/bin:/usr/local/share/npm/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin

上記の例では npm test で echo $PATH を実行するようにしています。
元の $PATH と比べると /usr/local/Cellar/node/0.10.24/lib/node_modules/npm/bin/node-gyp-bin:/private/tmp/node_modules/.bin:/usr/local/Cellar/node/0.10.24/bin が追加されていることがわかります。

パスの追加は npm の utils/lifecycle.js で行われているようです。
cf. https://github.com/joyent/node/blob/v0.10.24-release/deps/npm/lib/utils/lifecycle.js#L69-L90

なので、require(“./utils/lifecycle.js”) を実行している buiild, install, publish, restart, run-script, start, test, unbuild, update コマンド経由の場合はローカルのパッケージが優先されそうです。

というのを次の記事を読んで知ったんですが、割りと知られてる話なんですかね?
Executing A Project-Specific Node/NPM Package A-la “bundle exec” | ThoughtStream.new :derick_bailey

広告
Emacs で Helm をストレスなく使うための個人的な設定 (2) リスト要素のフィルタリングとかに便利そうな JavaScript を書いてみた
※このエントリーははてなダイアリーから移行したものです。過去のコメントなどはそちらを参照してください