NodeJS require a global module/package

2019-01-02 19:51发布

I'm trying to install globally and then use forever and forever-monitor like this:

npm install -g forever forever-monitor

I see the usual output and also the operations that copy the files to the global path, but then if I try to require("forever"); I get an error saying that the module wasn't found.

I'm using latest version of both node and npm and I already know about the change that npm made in global vs local install, but I really don't want to install localy on every project and I'm working on a platform that doesn't support link so npm link after a global install isn't possible for me.

My question is: why I can't require a globally installed package? Is that a feature or a bug? Or am I doing something wrong?

PS: Just to make it crystal clear: I don't want to install locally.

8条回答
余欢
2楼-- · 2019-01-02 20:11

You can put this line in your .profile file:

export NODE_PATH="$(npm config get prefix)/lib/node_modules"

This will make node use the global path.

查看更多
姐姐魅力值爆表
3楼-- · 2019-01-02 20:13

As per documentation, Node.js will search in the following locations by default:

  1. Path specified in the NODE_PATH environment variable.

    Note: NODE_PATH environment variable is set to a colon-delimited list of absolute paths.

  2. Current node_modules folder. (local)

  3. $HOME/.node_modules (global)

    Note: $HOME is the user's home directory.

  4. $HOME/.node_libraries (global)
  5. $PREFIX/lib/node (global)

    Note: $PREFIX is Node.js's configured node_prefix.

    To check the current value of node_prefix, run:

    node -p process.config.variables.node_prefix
    

    Note: Prefix corresponds to --prefix param during build and it's relative to process.execPath. Not to confuse with value from the npm config get prefix command.source

If the given module can't be found, that means it is not present in one of the above locations.

Location of global root folder where modules are installed can be printed by: npm root -g (by default the path is computed at run-time unless overridden in npmrc file).

Solution

You can try the following workarounds:

  • Specify your global module location in NODE_PATH environment variable. E.g.

    echo 'require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node
    

    To test and print the value of NODE_PATH, run:

    echo 'console.log(process.env.NODE_PATH); require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node 
    
  • For more permanent solution, link your $HOME/.node_modules global user folder to point to the root folder, by running this command:

    ln -vs "$(npm root -g)" "$HOME"/.node_modules
    

    Then re-test it via: echo 'require("forever")' | node command.

  • Temporary change the current folder to where the extension has been installed globally, before invoking the script. E.g.

    npm install -g forever
    cd "$(npm root -g)"
    echo 'require("forever")' | node
    cd -
    
  • Configure global installation destination in npm userconfig file (see: npm help 5 npmrc) or by userconfig param (--prefix).

    To display the current config, run: npm config list.

    To edit the current config, run: npm config edit.

  • Specify the full path of node modules location when calling require(). E.g.

    require("/path/to/sub/module")
    
  • Install the package to custom location, e.g.

    npm install forever -g --prefix "$HOME"/.node_modules
    

    However, the installation will go under ~/.node_modules/lib/node_modules/, so the location still needs to be added.

    See: npm local install package to custom location

  • Create a symlink in the current folder from the location of the global package. E.g.

    npm link forever
    
查看更多
春风洒进眼中
4楼-- · 2019-01-02 20:15

Apologies for the necromancy but I'm able to specify hard-coded paths to globally installed modules:

var pg = require("/usr/local/lib/node_modules/pg");

This isn't perfect but considering that Unity3d tries to "compile" all javascript that is included in the project directory I really can't install any packages.

查看更多
余生请多指教
5楼-- · 2019-01-02 20:18

For CLI utilities that depend on big modules, like puppeteer, I like to spawn a npm root -g and use it to require the global module.

try {
  const root = require('child_process').execSync('npm root -g').toString().trim()
  var puppeteer = require(root + '/puppeteer')
} catch (err) {
  console.error(`Install puppeteer globally first with: npm install -g puppeteer`)
  process.exit(1)
}
查看更多
牵手、夕阳
6楼-- · 2019-01-02 20:25

After you install package globally you have to link the local project with global package

npm install express -g
cd ~/mynodeproject/
npm link express  

See here

查看更多
笑指拈花
7楼-- · 2019-01-02 20:28

You can use the package requireg to solve this problem:

var forever = require('requireg')('forever')

will do the trick.

Also, there's another module, global-npm, while specific to just using the global npm, you can look at the short code and see how the technique works.

查看更多
登录 后发表回答