Attila Györffy Attila Györffy - 5 months ago 19
Node.js Question

Inconsistent behaviour when installing NPM packages globally

I'm trying to install NPM packages on Ubuntu (12.04). I've installed Node.js and NPM via Chris Lea's PPA repository.

I'm trying to deploy the Uptime project to my server. I've cloned the application from GitHub, then trying to install the application dependencies as a root user:

root@dev:/web/my-application# npm install -g
npm http GET https://registry.npmjs.org/mongoose/2.5.11
npm http GET https://registry.npmjs.org/express/2.5.0
npm http GET https://registry.npmjs.org/ejs/0.6.1
npm http GET https://registry.npmjs.org/config/0.4.11
npm http GET https://registry.npmjs.org/async/0.1.18
npm http GET https://registry.npmjs.org/socket.io/0.9.2
npm http 304 https://registry.npmjs.org/ejs/0.6.1
npm http 304 https://registry.npmjs.org/async/0.1.18
npm http 304 https://registry.npmjs.org/mongoose/2.5.11
npm http 304 https://registry.npmjs.org/express/2.5.0
npm http 304 https://registry.npmjs.org/config/0.4.11
npm http 304 https://registry.npmjs.org/socket.io/0.9.2
npm http GET https://registry.npmjs.org/mime
npm http GET https://registry.npmjs.org/connect
npm http GET https://registry.npmjs.org/mkdirp/0.0.7
npm http GET https://registry.npmjs.org/qs
npm http GET https://registry.npmjs.org/policyfile/0.0.4
npm http GET https://registry.npmjs.org/redis/0.6.7
npm http GET https://registry.npmjs.org/socket.io-client/0.9.2
npm http GET https://registry.npmjs.org/yaml
npm http GET https://registry.npmjs.org/vows
npm http GET https://registry.npmjs.org/coffee-script
npm http GET https://registry.npmjs.org/hooks/0.2.0
npm http GET https://registry.npmjs.org/mongodb/0.9.9-5
npm http 304 https://registry.npmjs.org/mime
npm http 304 https://registry.npmjs.org/connect
npm http 304 https://registry.npmjs.org/mkdirp/0.0.7
npm http 304 https://registry.npmjs.org/qs
npm http 304 https://registry.npmjs.org/policyfile/0.0.4
npm http 304 https://registry.npmjs.org/redis/0.6.7
npm http 304 https://registry.npmjs.org/socket.io-client/0.9.2
npm http 304 https://registry.npmjs.org/vows
npm http 304 https://registry.npmjs.org/yaml
npm http 304 https://registry.npmjs.org/coffee-script
npm http 304 https://registry.npmjs.org/hooks/0.2.0
npm http 304 https://registry.npmjs.org/mongodb/0.9.9-5
npm http GET https://registry.npmjs.org/eyes

> mongodb@0.9.9-5 install /usr/lib/node_modules/node-uptime/node_modules/mongoose/node_modules/mongodb
> node install.js

npm http 304 https://registry.npmjs.org/eyes
================================================================================
= =
= To install with C++ bson parser do <npm install mongodb --mongodb:native> =
= =
================================================================================
npm http GET https://registry.npmjs.org/uglify-js/1.2.5
npm http GET https://registry.npmjs.org/ws
npm http GET https://registry.npmjs.org/xmlhttprequest/1.2.2
npm http GET https://registry.npmjs.org/active-x-obfuscator/0.0.1
npm http 304 https://registry.npmjs.org/active-x-obfuscator/0.0.1
npm http 304 https://registry.npmjs.org/uglify-js/1.2.5
npm http 304 https://registry.npmjs.org/xmlhttprequest/1.2.2
npm http 304 https://registry.npmjs.org/ws
npm http GET https://registry.npmjs.org/zeparser/0.0.5
npm http GET https://registry.npmjs.org/commander
npm http GET https://registry.npmjs.org/options
npm http 304 https://registry.npmjs.org/zeparser/0.0.5
npm http 304 https://registry.npmjs.org/options
npm http 304 https://registry.npmjs.org/commander

> ws@0.4.16 install /usr/lib/node_modules/node-uptime/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws
> node install.js

================================================================================
= =
= To install WS with blazing fast native extensions, use =
= <npm install ws --ws:native> =
= =
================================================================================
node-uptime@1.2.0 /usr/lib/node_modules/node-uptime
├── async@0.1.18
├── ejs@0.6.1
├── express@2.5.0 (mkdirp@0.0.7, mime@1.2.5, qs@0.5.0, connect@1.7.3)
├── mongoose@2.5.11 (hooks@0.2.0, mongodb@0.9.9-5)
├── config@0.4.11 (yaml@0.2.3, coffee-script@1.3.3, vows@0.5.13)
└── socket.io@0.9.2 (policyfile@0.0.4, redis@0.6.7, socket.io-client@0.9.2)


All looking good, the packages seem to be installed successfully. However, when I'm checking if the NPM package dependencies are met, I'm getting a bunch of unmet dependencies listed, like I did not even install them just a second ago:

root@dev:/web/my-application# npm list
npm WARN mongoose 2.5.11 Unmet dependency in /web/my-application
npm WARN active-x-obfuscator 0.0.1 Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
npm WARN uglify-js 1.2.5 Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
npm WARN ws 0.4.x Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
npm WARN xmlhttprequest 1.2.2 Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
node-uptime@1.2.0 /web/my-application
├── async@0.1.18
├─┬ config@0.4.11
│ ├── coffee-script@1.3.3
│ ├─┬ vows@0.5.13
│ │ └── eyes@0.1.7
│ └── yaml@0.2.3
├── ejs@0.6.1
├─┬ express@2.5.0
│ ├── connect@1.7.3
│ ├── mime@1.2.5
│ ├── mkdirp@0.0.7
│ └── qs@0.5.0
├── UNMET DEPENDENCY mongoose 2.5.11
└─┬ socket.io@0.9.2
├── policyfile@0.0.4
├── redis@0.6.7
└─┬ socket.io-client@0.9.2
├── UNMET DEPENDENCY active-x-obfuscator 0.0.1
├── UNMET DEPENDENCY uglify-js 1.2.5
├── UNMET DEPENDENCY ws 0.4.x
└── UNMET DEPENDENCY xmlhttprequest 1.2.2


As far as I know (but correct me if I'm wrong) NPM respects the
NODE_PATH
environment variable when installing packages globally. Funnily enough if you look at the package install output above, you can see that NPM installed dependant packages globally into
/usr/lib/node_modules
. If I double check the
NODE_PATH
environment variable, it turns out that the
NODE_PATH
variable is set differently:

root@dev:/web/my-application# echo $NODE_PATH
/usr/lib/nodejs:/usr/share/javascript


One thing to clarify: I don't know how the
NODE_PATH
variable has been set, I have not set it myself and I've got a feeling that it came with the Ubuntu package when I installed Node and NPM.

Then I decided to explicitly set the
NODE_PATH
variable and double check the dependencies:

root@dev:/web/my-application# export NODE_PATH=/usr/lib/node_modules
root@dev:/web/my-application# npm list
npm WARN mongoose 2.5.11 Unmet dependency in /web/my-application
npm WARN active-x-obfuscator 0.0.1 Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
npm WARN uglify-js 1.2.5 Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
npm WARN ws 0.4.x Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
npm WARN xmlhttprequest 1.2.2 Unmet dependency in /web/my-application/node_modules/socket.io/node_modules/socket.io-client
node-uptime@1.2.0 /web/my-application
├── async@0.1.18
├─┬ config@0.4.11
│ ├── coffee-script@1.3.3
│ ├─┬ vows@0.5.13
│ │ └── eyes@0.1.7
│ └── yaml@0.2.3
├── ejs@0.6.1
├─┬ express@2.5.0
│ ├── connect@1.7.3
│ ├── mime@1.2.5
│ ├── mkdirp@0.0.7
│ └── qs@0.5.0
├── UNMET DEPENDENCY mongoose 2.5.11
└─┬ socket.io@0.9.2
├── policyfile@0.0.4
├── redis@0.6.7
└─┬ socket.io-client@0.9.2
├── UNMET DEPENDENCY active-x-obfuscator 0.0.1
├── UNMET DEPENDENCY uglify-js 1.2.5
├── UNMET DEPENDENCY ws 0.4.x
└── UNMET DEPENDENCY xmlhttprequest 1.2.2


Still no success, however when I am trying to run the application with node, it successfully initializes and runs:

root@dev:/web/my-application# node app.js
Monitor origin started
info - socket.io started
Express server listening on port 8082 in development mode
Mongoose: pings.ensureIndex({ timestamp: -1 }) {}
Mongoose: checkevents.ensureIndex({ timestamp: -1, check: 1 }) {}
Mongoose: checkhourlystats.ensureIndex({ timestamp: -1, check: 1 }) { unique: true }
Mongoose: checkdailystats.ensureIndex({ timestamp: -1, check: 1 }) { unique: true }
Mongoose: checkmonthlystats.ensureIndex({ timestamp: -1, check: 1 }) { unique: true }
Mongoose: checks.find({ '$where': 'function () {\n if (this.isPaused) return false;\n if (!this.firstTested) return true;\n var delay = (this.lastTested.getTime() - this.firstTested.getTime()) % this.interval;\n return (Date.now() - this.lastTested.getTime() + delay) >= (this.interval || 60000);\n}' }) { fields: { qos: 0 }, safe: true }
Mongoose: taghourlystats.ensureIndex({ timestamp: -1, name: 1 }) { unique: true }
Mongoose: tagdailystats.ensureIndex({ timestamp: -1, name: 1 }) { unique: true }
Mongoose: tagmonthlystats.ensureIndex({ timestamp: -1, name: 1 }) { unique: true }
Mongoose: tags.ensureIndex({ name: 1 }) { unique: true }


This looks like it is going to be OK from now, however I am definitely not going to run the application as root so I will need the global NPM packages to be recognised when I'll run the app as a dedicated user.

I have a feeling that NPM has some sort of inconsistent behaviour when installing packages. When installing globally, it runs successfully but then it fails to retrieve those afterwards.

What can I do, and also, how does one's
NODE_PATH
environment variable look like
?

Answer

You have to install it with just npm install -d, without -g. The requirements of packages are local for every package (so that you have node_modules\a when you depend on a, and node_modules\a\node_modules\b, when a depends on b).

See http://npmjs.org/doc/faq.html#I-installed-something-globally-but-I-can-t-require-it for more details.