No Need for npm -g
UPDATE: please see my new article on Managing Per-project Interpreters and the PATH for a new and improved take on this topic.
So npm has this "-g" switch to install "global" packages that bundle command line executable scripts. I've been on a strict project isolation kick lately after dealing with rbenv in the ruby world, and I just don't see any need for npm -g
. I want each project to have its own version of node, coffeescript, mocha, or whatever else I need. Here's my principles for a harmonious multi-project system.
1. Install things under your project root
Node goes in project/node
.
Install npm modules without -g
. coffee
becomes project/node_modules/.bin/coffee
. mocha
becomes project/node_modules/.bin/mocha
. And so on.
2. Set your PATH
Add ./node/bin:./node_modules/.bin
and to your PATH
.
Done
Here's an example.
$ mkdir project1 project2
$ cd project1
$ npm install coffee-script@1.0.1
coffee-script@1.0.1 ./node_modules/coffee-script
$ which coffee
./node_modules/.bin/coffee
$ coffee --version
CoffeeScript version 1.0.1
$ cd ../project2
$ npm install coffee-script@1.2.0
coffee-script@1.2.0 ./node_modules/coffee-script
$ which coffee
./node_modules/.bin/coffee
$ coffee --version
CoffeeScript version 1.2.0
Same principle works for node
and any scripts you get from npm modules.
While we're talking about PATH
, here's how I set my PATH
in my ~/.zshrc
. It's nice because I can throw a bunch of crap in there that may or may not exist on any given computer and only directories that exist get into my PATH
.
########## PATH ##########
PATH=
addPath() {
if [ -d "${1}" ]; then
export PATH=$PATH:"${1}"
fi
}
addPath ./node_modules/.bin
addPath ./node/bin
#Repeat addPath lines for each directory...
export PATH
Security Caveat About Relative Paths in PATH
Having relative directory paths in your PATH
is arguably a security vulnerability. See also slide 20 here. I'm not personally too concerned about this one for my personal interactive login shell. However, this practice is probably not suitable for shell scripts that are run as programs. Also note that in a production deployment you should launch your node
or coffee
executable via an absolute path when coding your upstart or SysV init script.