225

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.

alexandernst
  • 14,352
  • 22
  • 97
  • 197
  • I just leave it here https://github.com/yarnpkg/yarn/issues/2049 https://github.com/yarnpkg/yarn/issues/2049#issuecomment-337870443 – Marecky Aug 23 '18 at 22:27
  • Possible duplicate of [How do I import global modules in Node? I get "Error: Cannot find module "?](https://stackoverflow.com/questions/7970793/how-do-i-import-global-modules-in-node-i-get-error-cannot-find-module-module) – Skippy le Grand Gourou Apr 19 '19 at 09:52
  • so it's `~/.config/yarn/global` for yarn – localhostdotdev May 15 '19 at 23:41

9 Answers9

279

In Node.js, require doesn't look in the folder where global modules are installed.

You can fix this by setting the NODE_PATH environment variable. In Linux this will be:

export NODE_PATH=/usr/lib/node_modules

Note that it depends on where your global modules are actually installed.

For a more sustainable solution, you can dynamically set your NODE PATH to:

export NODE_PATH=$(npm root -g)

See: Loading from the global folders.

Flavio Wuensche
  • 9,460
  • 1
  • 57
  • 54
Daniel Uzunu
  • 3,086
  • 1
  • 12
  • 9
  • 27
    On my Ubuntu 13.10 machine, the global path for modules is different than you show here. I had to use `export NODE_PATH=/usr/local/lib/node_modules` instead. – Drew Noakes Jan 10 '14 at 20:16
  • 12
    If you're on Windows 7 / 8 and haven't overridden any of Node's install defaults, setting the `NODE_PATH` environment variable to `C:\Users\{USERNAME}\AppData\Roaming\npm\node_modules` will likely work. – Wes Johnson Feb 19 '14 at 19:59
  • 5
    @WesJohnson Just `%AppData%\npm\node_modules` will work on Windows 10. – theblang Nov 02 '15 at 03:26
  • 6
    If I set `NODE_PATH` can I use global and local modules simultaneously? – Paulo Oliveira Mar 18 '16 at 02:05
  • @DrewNoakes same path in alpine linux – lifeisfoo Feb 14 '17 at 09:23
  • 2
    This is not working for me. I've set the NODE_PATH to the exact location of globally installed node_modules but simple require('module_name') still doesn't work. (using linux) – Carmela Apr 04 '17 at 10:18
  • @Carmela, you must export NODE_PATH in the shell process where you actually start node. – Király István Sep 11 '18 at 23:59
  • 20
    Alternatively instead of a static path, i.e. if you are using NVM: `NODE_PATH=$(npm root -g)` – holmberd May 30 '19 at 14:05
  • `export NODE_PATH=$(npm root -g)` also works for [n](https://github.com/tj/n) – Henrique Bruno Apr 06 '21 at 19:54
  • @holmberd definitely the preferred answer! Do you happen to know if there's a hook in nvm so that it will automatically be re-exported following `nvm use`? – Jeff Mar 04 '22 at 15:48
  • @Jeff not that I know off. You can always create an alias for `nvm use` to also exec `source`. – holmberd Mar 04 '22 at 16:18
  • I recall reading in some relatively intro npm doc "if you want to require() from a package, install it in the local project". IIRC correctly they don't even document there how to do this globally, I guess they don't want you to know for some reason – Britton Kerin Sep 10 '22 at 21:39
124

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

Sandy Gifford
  • 7,219
  • 3
  • 35
  • 65
user568109
  • 47,225
  • 17
  • 99
  • 123
  • 2
    I'm running on a platform that doesn't support link (as my question states) http://blog.nodejs.org/2011/04/06/npm-1-0-link/ – alexandernst Mar 26 '13 at 14:16
  • 1
    which platform are you using ? – user568109 Mar 26 '13 at 14:25
  • I'm on Windows XP. I'm de deploying to a Linux machine (which does support link). Anyways, I'd like to be able to require modules on my dev machine (the XP one) – alexandernst Mar 26 '13 at 14:30
  • can u try fsutil for symlink it looks like some work but worth trying http://serverfault.com/questions/7109/how-do-i-create-a-symbolic-link-in-windows – user568109 Mar 26 '13 at 14:41
  • 2
    I really don't want to mess with link (nor symbolic links at all). I just want to install packages globally and require them. I know NPM was re-designed to avoid this, but how hard could it be to achieve something like this? – alexandernst Mar 26 '13 at 14:44
  • 18
    What if I don't have a project? Say `~/some-stand-alone-random-nodejs-test.js`. I don't want to turn my home folder into a project directory. I don't want to create new folders for every small experiment. – AnnanFay Jul 10 '14 at 20:40
  • 1
    Worked perfect on Windows 8.1. From node command line **cd** to my projects' local node_modules folder then executed `npm link ` Then you will see a shortcut(link) created in your projects' **node_module** folder referencing the global node module. – dynamiclynk Sep 25 '14 at 14:11
  • 1
    watch out, if you ever remove the project, including the `node_modules` folder, you'll remove your global module installation – Flion Jan 20 '16 at 00:13
  • 1
    @flion That varies greatly depending on which OS and which method you use to remove the files. Every OS which uses symlinks (or shortcuts) provides a method to remove the link without removing the target; but yes, you do need to be careful. – jpaugh Jan 04 '18 at 16:56
36

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.

jpaugh
  • 6,634
  • 4
  • 38
  • 90
Thomas Ingham
  • 1,082
  • 8
  • 16
  • 4
    Unity3D doesn't support JavaScript.  It supports a JS-like syntax for its Boo interpreter/compiler _(Boo is a Python-like language for .NET)_ **that is deceptively marketed as “JavaScript”**.  The more-accurate name for the language Unity supports is **UnityScript**.  Because it's not even close to the same language, next to none of the JS written for the web or for Node.js will work in Unity.  Much more info on the differences on the official Unity wiki: http://wiki.unity3d.com/index.php/UnityScript_versus_JavaScript – Slipp D. Thompson Mar 12 '17 at 08:00
  • or for custom global path `var pg = require('/home//.npm-global/lib/node_modules/pg')` – Vlad Aug 04 '20 at 07:37
  • 1
    Never apologize for necromancy. It's [a badge](https://stackoverflow.com/help/badges/17/necromancer) for cryin' out loud. ;^) – ruffin Sep 10 '20 at 21:17
29

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
    
kenorb
  • 155,785
  • 88
  • 678
  • 743
23

I know this is an old question, but I ran into this when trying to do some version checking using semver in a preinstall script in package.json. Since I knew I can't depend on any local modules installed, I used this to require semver from the global node_modules folder (as npm depends on it I know it's there):

function requireGlobal(packageName) {
  var childProcess = require('child_process');
  var path = require('path');
  var fs = require('fs');

  var globalNodeModules = childProcess.execSync('npm root -g').toString().trim();
  var packageDir = path.join(globalNodeModules, packageName);
  if (!fs.existsSync(packageDir))
    packageDir = path.join(globalNodeModules, 'npm/node_modules', packageName); //find package required by old npm

  if (!fs.existsSync(packageDir))
    throw new Error('Cannot find global module \'' + packageName + '\'');

  var packageMeta = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json')).toString());
  var main = path.join(packageDir, packageMeta.main);

  return require(main);
}

I like this approach because this doesn't require the install of any special modules in order to use.

I didn't go with a NODE_PATH solution like others have suggested since I wanted to get this to work on anyone's machine, without having to require additional configuration/setup before running npm install for my project.

The way this is coded, it is only guaranteed to find top-level modules (installed using npm install -g ...) or modules required by npm (listed as dependencies here: https://github.com/npm/npm/blob/master/package.json). If you are using a newer version of NPM, it may find dependencies of other globally installed packages since there is a flatter structure for node_modules folders now.

Hope this is useful to someone.

Joe Skeen
  • 1,727
  • 16
  • 18
17

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.

JP Richardson
  • 38,609
  • 36
  • 119
  • 151
  • interesting, but the NODE_PATH method is probably more canonical – Alexander Mills May 21 '16 at 21:43
  • the beauty of `NODE_PATH` is also, that you don't need to change any code. (my use case is grading a lot of student projects, where I don't want to run `npm install` for each one, and also don't want them to provide `node_modules` directory). – amenthes Feb 12 '17 at 10:06
  • 4
    No, it will not do the trick because you can't require `requireg` in the first place, this is the whole point. – thisismydesign Dec 11 '19 at 21:07
  • i was having issues with shellJs + typescript + ncc + docker working properly. This answer lead me down the right path and finally got it to work using a globally installed shelljs and requireq. `let shell = require("requireg")("shelljs");` – Kenneth Garza Jul 14 '21 at 21:28
13

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)
}
Christophe Marois
  • 6,471
  • 1
  • 30
  • 32
6

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.

Luis Paulo
  • 421
  • 5
  • 10
  • 1
    No. This is the generic way of getting the global `node_modules`. This is an old answer but I remember I got it from somwhere in the documentation. Anyway, in my computer (in 2020) the global npm `node_modules` directory is `usr/lib/node_modules`. Anyway, I trust `npm config get prefix` because it is used globally by npm whenever a global package is installed so it should be right. – Luis Paulo Feb 07 '20 at 17:47
  • 1
    Either way (I didn't say this in my initial answer because I wasn't very experienced in Node.JS), using globally installed packages in a program is an edge use case and should seldom be done because in a project it will create problems whenever the project is committed to VCS and cloned in another environment due to that specific dependency not being in the `package.json` file or in `yarn.lock`/`package-lock.json`. – Luis Paulo Feb 07 '20 at 17:50
  • 1
    Oh! I understand now. I believe you're mistaking the NODE_PATH with PATH. PATH is where a shell will look for executables. NODE_PATH is where node will look for packages. It will start by looking at the current directory for a `node_modules` folder, then it's parent, then it's parent, ... until it finds a `node_modules` folder which contains that module. However, if you install a package globally, it won't be inside any `node_modules` folder above the script's current directory so you use NODE_PATH as a fallback where node will look for packages. – Luis Paulo Feb 07 '20 at 21:13
  • 1
    ahahahah @Luis Paulo you're totally right!! I'm sorry! I'll try and delete some of my comments to prevent confusion, nice job and thank you – Ryan Taylor Feb 11 '20 at 19:30
  • @Ryan Taylor You shouldn't delete comments and questions once they get resolved because someone else could have the same ones. Now it just looks like I had a monologue in the comments! ahahahah – Luis Paulo Feb 14 '20 at 10:54
  • Thanks man! I appreciate it, it's working fine now. JIC I want to mention that I could fix it on macOS – Leo Gasparrini Oct 29 '20 at 06:11
0

i tried following the other answers but what worked for me was

      node_path = "C:\\Users\\{usename}\\AppData\\Roaming\\npm\\node_modules"
      const *modulename* = require(node_path + "\\" +'*modulename*');