biril biril - 5 months ago 72
Node.js Question

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:


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

  • Is 2) the correct way to go about doing this? or is there some other practice I'm missing?


Answer

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..?)