biril
biril

Reputation: 1995

Node / npm: How to manage globally installed devDependencies

I'm building a Node module with devDependencies that should be globally installed, such as jasmine-node and jshint. What I essentially need is to be able to reference their binaries in my makefile / npm scripts section to run tests, lint, etc. In other words I do not wish to require() them programmatically.

After digging around I'm still confused on how to handle this:

1) My first approach was to assume that these modules would be globally installed, clarify this in my module's documentation and reference their binaries as globals - i.e. expect them to be globally available. This conflicts with this piece of advice

Make sure you avoid referencing globally installed binaries. Instead, point it to the local node_modules, which installs the binaries in a hidden .bin directory. Make sure the module (in this case "mocha") is in your package.json under devDependencies, so that the binary is placed there when you run npm install.

(taken from this post)

This generally sounds right, as the aforementioned setup is rather fragile.

2) My next approach was explicitly including those modules in devDependencies (although they are still globally installed on my system (and most probably on users' & contributors' systems as well)). This ensures that appropriate versions of the binaries are there when needed and I can now reference them through node_modules/.bin/.

However I'm now in conflict with this piece of advice

Install it locally if you're going to require() it.

(taken from npm docs)

Regardless of that, I do notice that npm install will now actually fetch nothing (display no network activity) for the globally installed modules.


My questions:

Upvotes: 7

Views: 2362

Answers (2)

biril
biril

Reputation: 1995

Revisiting my own question a couple of years after it was originally written, I feel I can now safely say that the quoted 'advice'

Install it locally if you're going to require() it.

does not stand anymore. (It was part of the npm docs but the posted 2-year old link gives me a 404 at the time of this writing.)

Nowadays, npm run is a fine way to do task management / automation and it'll automatically export modules which are installed locally, into the path before executing. Thus, it makes perfect sense to locally install modules that are not to be require()d such as linters and test-runners. (By the way, this is completely in line with the answer that Peter Lyons provided a couple of years ago - it may have been 'decidedly divergent from node.js common practice' back then, but it's pretty much widely accepted today :))

As for my second question

Are the local versions of globally installed modules (that are mentioned in devDependencies) just snapshots (copies) of the global ones, taken during npm install?

I am pretty confident that the answer is No. (Perhaps the lack of network activity that I was observing back then, during the installation of local modules which were also globally installed was due to caching..?)


Note, Nov 12 2016

The relevant npm docs to which the original question linked have moved here.

Upvotes: 2

Peter Lyons
Peter Lyons

Reputation: 146014

Here's my personal take on this, which is decidedly divergent from node.js common practice, but I believe it is an overall superior approach. It is detailed in my own blog post (disclaimer about self-promotion, yada yada) Managing Per-Project Interpreters and the PATH.

It basically boils down to:

  1. Never use npm -g. Never install global modules.
  2. Instead, adjust your PATH to include projectDir/node_modules/.bin instead

Upvotes: 7

Related Questions