title: npm 1.0: Global vs Local installation author: Isaac Schlueter date: Wed Mar 23 2011 23:07:13 GMT-0700 (PDT) status: publish category: npm slug: npm-1-0-global-vs-local-installation
npm 1.0 is in release candidate mode. Go get it!
More than anything else, the driving force behind the npm 1.0 rearchitecture was the desire to simplify what a package installation directory structure looks like.
In npm 0.x, there was a command called bundle
that a lot of people liked. bundle
let you install your dependencies locally in your project, but even still, it was basically a hack that never really worked very reliably.
Also, there was that activation/deactivation thing. That’s confusing.
In npm 1.0, there are two ways to install things:
{prefix}/lib/node_modules
, and puts executable files in {prefix}/bin
, where {prefix}
is usually something like /usr/local
. It also installs man pages in {prefix}/share/man
, if they’re supplied../node_modules
, executables go in ./node_modules/.bin/
, and man pages aren’t installed at all.Whether to install a package globally or locally depends on the global
config, which is aliased to the -g
command line switch.
Just like how global variables are kind of gross, but also necessary in some cases, global packages are important, but best avoided if not needed.
In general, the rule of thumb is:
require('whatever')
, then install it locally, at the root of your project.PATH
environment variable.Of course, there are some cases where you want to do both. Coffee-script and Express both are good examples of apps that have a command line interface, as well as a library. In those cases, you can do one of the following:
npm link coffee-script
or npm link express
(if you’re on a platform that supports symbolic links.) Then you only need to update the global copy to update all the symlinks as well.The first option is the best in my opinion. Simple, clear, explicit. The second is really handy if you are going to re-use the same library in a bunch of different projects. (More on npm link
in a future installment.)
You can probably think of other ways to do it by messing with environment variables. But I don’t recommend those ways. Go with the grain.
Let’s say you do something like this:
cd ~/projects/foo # go into my project
npm install express # ./node_modules/express
cd lib/utils # move around in there
vim some-thing.js # edit some stuff, work work work
npm install redis # ./lib/utils/node_modules/redis!? ew.
In this case, npm will install redis
into ~/projects/foo/node_modules/redis
. Sort of like how git will work anywhere within a git repository, npm will work anywhere within a package, defined by having a node_modules
folder.
If your package's scripts.test
command uses a command-line program installed by one of your dependencies, not to worry. npm makes ./node_modules/.bin
the first entry in the PATH
environment variable when running any lifecycle scripts, so this will work fine, even if your program is not globally installed:
{ "name" : "my-program"
, "version" : "1.2.3"
, "dependencies": { "express": "*", "coffee-script": "*" }
, "devDependencies": { "vows": "*" }
, "scripts":
{ "test": "vows test/*.js"
, "preinstall": "cake build" } }