Nvm: NODE_PATH should not point to globally installed packages

Created on 28 Nov 2014  ·  14Comments  ·  Source: nvm-sh/nvm

It seems that nvm by default sets NODE_PATH to point to the directory with globally installed packages. Official Node.js installation does not do that however. This leads to differences in behavior between nvm and official distribution: with nvm you can require globally installed modules, with official node.js you cannot.

According to npm-faq you should not require modules from global packages.

bugs

Most helpful comment

Hmm, yeoman shouldn't need that - global modules should not be requireable.

@artm However, this actually seems like correct behavior - since adding npm root -g to your NODE_PATH is nonstandard, the error message is telling you exactly how to fix it.

You can modify it for nvm by adding this line to your bashrc instead, after the nvm sourcing:

export NODE_PATH=$NODE_PATH:`npm root -g`

which will only work when the shell is opened, but will at least follow the default alias or nvmrc you've selected.

All 14 comments

Wow, good call. Global modules should definitely not be requireable.

@creationix, @koenpunt, any idea why this was the case originally?

Released as v0.20.0

Don't know, it was your call in #342

Doh! Thanks, you're entirely correct.

This breaks yeoman looking for globally installed generators, which makes yo doctor say:

$ yo doctor
[Yeoman Doctor] Uh oh, I found potential errors on your machine
---------------

[Error] npm root value is not in your NODE_PATH
  [info]
    NODE_PATH = /usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript
    npm root  = /home/artm/.nvm/v0.10.35/lib/node_modules

  [Fix] Append the npm root value to your NODE_PATH variable
    Add this line to your .bashrc
      export NODE_PATH=$NODE_PATH:/home/artm/.nvm/v0.10.35/lib/node_modules
    Or run this command
      echo "export NODE_PATH=$NODE_PATH:/home/artm/.nvm/v0.10.35/lib/node_modules" >> ~/.bashrc && source ~/.bashrc

Hmm, yeoman shouldn't need that - global modules should not be requireable.

@artm However, this actually seems like correct behavior - since adding npm root -g to your NODE_PATH is nonstandard, the error message is telling you exactly how to fix it.

You can modify it for nvm by adding this line to your bashrc instead, after the nvm sourcing:

export NODE_PATH=$NODE_PATH:`npm root -g`

which will only work when the shell is opened, but will at least follow the default alias or nvmrc you've selected.

Thanks for the suggestion!

I suspect non-requirability of global modules was formuted before yeoman came up with their solutions to loosely coupled generators. Specifically this assumption of the npm FAQ doesn't hold:

If you require() a module in your code, then that means it's a dependency, and a part of your program.

In case of a yeoman generator, a generator is a third party plugin which is required dynamically by a
_command-line utility in the system PATH_ (yo). Yeoman doesn't depend on any specific generator, it depends on them being requireable while globally installed. They have to be installed globally, because they are used to generate a project before it has any local modules or npm configuration (it is in fact the generator who populates the package.json).

Disclaimer: I'm only learning about yeoman for the first time today, I could be mistaken in my own assumptions.

You may be right about yeoman - but the model you're describing is "peer dependencies", which the larger community has mostly decided is an unwise design (ie, plugin models of any kind).

@ljharb sometimes it could be useful to require a global installed module, ex: npm to retrieve npm config settings.

@g13013 If you're doing that, then npm is a dependency, and you should be installing it locally (https://github.com/tbranyen/salita/blob/master/package.json#L22 for example).

It might be sometimes _useful_ but it's never a good idea, because it makes your apps' actual dependencies not explicit.

@ljharb you got a point 👍

Hijacking this thread with a related question for which I couldn't find an answer elsewhere.

@ljharb says

Global modules should definitely not be requireable.

Which is explained in npm-faq / "I installed something globally, but I can't require() it":

Install it locally.

The global install location is a place for command-line utilities to put their bins in the system PATH. It's not for use with require().

If you require() a module in your code, then that means it's a dependency, and a part of your program. You need to install it locally in your program.

Okay. Now my use case is that I want _some_ packages installed globally and requireable, so that I can run node from anywhere and require() them to fiddle with and explore their API. For example, lodash and superagent.

  • _"Just install them locally"_ doesn't make much sense to me, because the js project I'm using them for isn't even node-based, I just happen to use node as a REPL (that is more convenient than the unfriendly js environment I'm currently working in). A workaround I can see is to install such packages locally "somewhere", and make an alias doing something like PWD=/path/to/local/install node.
  • Then, there's node's module loading from global folders, but it's definitely a no-no with nvm.

→ Is there a nicer way to accomplish what I want (globally installed, require()able modules) ? Or, taking a step back, what could I do differently?

@ronjouch npm link is the typical answer, but for your use case, just make a directory you can cd to, and run the node repl there - and it can have all the things you want locally preinstalled.

Was this page helpful?
0 / 5 - 0 ratings