217

Is it possible to specify a custom package destination for npm install, either through a command flag or environment variable?

By default, npm local installs end up in node_modules within the current directory, but I want it to install into node_modules within a different directory, for example vendor/node_modules. How can I make that happen?

Matko
  • 3,386
  • 4
  • 21
  • 35
pje
  • 21,801
  • 10
  • 54
  • 70
  • what are you trying to accomplish? this has been discussed here: http://stackoverflow.com/questions/13668097/how-to-replace-npm-node-module-folder-with-another-folder – Pascal Belloncle Feb 07 '13 at 02:42
  • 12
    @PascalBelloncle: Instead of installing packages into subdirectories of `./node_modules`, I want npm to install them into subdirectories of `./vendor/node_modules`. (Or to be told that that isn't configurable.) – pje Feb 07 '13 at 02:49
  • 1
    I understood that's what you want to do, which I don't think is possible out of the box. Plus require would not work either. So I was asking why you wanted to do this. Maybe there is an alternative solution to do what you want. – Pascal Belloncle Feb 07 '13 at 02:52
  • 1
    I'm installing a package solely for its binary (i.e. it will only be used on the command line and never `require`d) but I don't want to install it globally. – pje Feb 07 '13 at 02:58
  • I see. See my suggestion below then. – Pascal Belloncle Feb 07 '13 at 03:02

5 Answers5

205

TL;DR

You can do this by using the --prefix flag and the --global* flag.

pje@friendbear:~/foo $ npm install bower -g --prefix ./vendor/node_modules
bower@0.7.0 /Users/pje/foo/vendor/node_modules/bower

*Even though this is a "global" installation, installed bins won't be accessible through the command line unless ~/foo/vendor/node_modules exists in PATH.

TL;DR

Every configurable attribute of npm can be set in any of six different places. In order of priority:

  • Command-Line Flags: --prefix ./vendor/node_modules
  • Environment Variables: NPM_CONFIG_PREFIX=./vendor/node_modules
  • User Config File: $HOME/.npmrc or userconfig param
  • Global Config File: $PREFIX/etc/npmrc or userconfig param
  • Built-In Config File: path/to/npm/itself/npmrc
  • Default Config: node_modules/npmconf/config-defs.js

By default, locally-installed packages go into ./node_modules. global ones go into the prefix config variable (/usr/local by default).

You can run npm config list to see your current config and npm config edit to change it.

PS

In general, npm's documentation is really helpful. The folders section is a good structural overview of npm and the config section answers this question.

mik3fly-4steri5k
  • 712
  • 3
  • 15
  • 32
pje
  • 21,801
  • 10
  • 54
  • 70
  • 2
    As I test, actually if follow the command above, it will be installed into `./vendor/node_modules/lib/bower` using `npm#3.8.0` – e-cloud Mar 11 '16 at 03:05
  • 3
    When doing this, I am getting error `No version provided in package.json` – FooBar Aug 30 '16 at 20:06
  • You write `bins won't be accessible through the command line`. The program can of course be invoked using the complete path `npm install eslint@3.4.0 -g --prefix c:\my_npm\` calling `c:\my_npm\eslint --fix my.js` – Bernhard Döbler Oct 14 '16 at 09:10
  • 19
    Is it possible to achieve something similar with a package.json file? i.e. if I run `npm install` in directory A with package.json file, packages will be install in directory B. It seems this solution is for individual packages being installed. – Ryan-Neal Mes Nov 16 '16 at 14:53
  • 1
    Is there any way of installing all dependencies using this method? `npm install` installs dependencies locally. `npm install X -g -prefix "..."` installs module X to the prefix, `npm install -g -prefix "..."` installs the current package to the prefix. – AnnanFay Aug 04 '18 at 16:19
  • 1
    So my understanding from this answer is, I cannot stop npm littering my user `%userprofile%` , %appdata%, environment variables, etc.? How do I tell npm that it is not allowed to bring his toys to living room, kitchen and hallway and generally all over place or in other words it only can keep his toys in his own room at `D:\Projects\`? – AaA Jun 21 '19 at 06:36
37

If you want this in config, you can set npm config like so:

npm config set prefix "$(pwd)/vendor/node_modules"

or

npm config set prefix "$HOME/vendor/node_modules"

Check your config with

npm config ls -l

Or as @pje says and use the --prefix flag

Rimian
  • 36,864
  • 16
  • 117
  • 117
  • 9
    I believe this sets the global prefix? So doing `npm install` will still install locally to `./node_modules` but `npm install -g` will install to `"$(pwd)/vendor/node_modules"`. I can imagine settings this then forgetting about it, coming back later wondering why my global packages are acting weirdly. – AnnanFay Aug 04 '18 at 15:36
16

For OSX, you can go to your user's $HOME (probably /Users/yourname/) and, if it doesn't already exist, create an .npmrc file (a file that npm uses for user configuration), and create a directory for your npm packages to be installed in (e.g., /Users/yourname/npm). In that .npmrc file, set "prefix" to your new npm directory, which will be where "globally" installed npm packages will be installed; these "global" packages will, obviously, be available only to your user account.

In .npmrc:

prefix=${HOME}/npm

Then run this command from the command line:

npm config ls -l

It should give output on both your own local configuration and the global npm configuration, and you should see your local prefix configuration reflected, probably near the top of the long list of output.

For security, I recommend this approach to configuring your user account's npm behavior over chown-ing your /usr/local folders, which I've seen recommended elsewhere.

Rimian
  • 36,864
  • 16
  • 117
  • 117
Ryan
  • 911
  • 8
  • 7
10

On Windows 7 for example, the following set of commands/operations could be used.

Create an personal environment variable, double backslashes are mandatory:

  • Variable name: %NPM_HOME%
  • Variable value: C:\\SomeFolder\\SubFolder\\

Now, set the config values to the new folders (examplary file names):

  • Set the npm folder

npm config set prefix "%NPM_HOME%\\npm"

  • Set the npm-cache folder

npm config set cache "%NPM_HOME%\\npm-cache"

  • Set the npm temporary folder

npm config set tmp "%NPM_HOME%\\temp"

Optionally, you can purge the contents of the original folders before the config is changed.

  • Delete the npm-cache npm cache clear

  • List the npm modules npm -g ls

  • Delete the npm modules npm -g rm name_of_package1 name_of_package2

MichaelHuelsen
  • 386
  • 1
  • 4
  • 11
  • 2
    Thanks, I follow the steps. But it creates a directory called c:/%NPM_HOME%/npm, etc. instead of c:/npm_home/npm – Jay Nov 24 '17 at 16:09
8

After searching for this myself wanting several projects with shared dependencies to be DRYer, I’ve found:

  • Installing locally is the Node way for anything you want to use via require()
  • Installing globally is for binaries you want in your path, but is not intended for anything via require()
  • Using a prefix means you need to add appropriate bin and man paths to $PATH
  • npm link (info) lets you use a local install as a source for globals

→ stick to the Node way and install locally

ref:

Oli Studholme
  • 2,600
  • 22
  • 16