npm install | how it works

If you're new to npm, start here...

npm install downloads a package and it's dependencies.

npm install can be run with or without arguments.

When run without arguments, npm install downloads dependencies defined in a package.json file and generates a node_modules folder with the installed modules.

When run with arguments, npm install downloads specific modules to the node_modules folder.

The package.json file dictates what modules will get installed in the node_modules folder. It's important that npm install is run in the same location as the package.json file.

Let's look at some examples in more detail...

npm install (no arguments)

npm install
npm i

Both of these commands do the same thing. Running npm install without arguments installs modules defined in the dependencies section of the package.json file.

It's important that npm install is run in the same directory as the package.json file.

The downloaded modules are placed in a node_modules folder in the same location as package.json.

npm install also generates a package-lock.json file. This file describes the exact dependency tree that was installed. This makes it easier for subsequent installs to use the exact same tree (regardless of intermediate dependency updates).

npm dependency resolution

What's this tree you ask? Remember that npm install downloads a package and any dependencies it relies on. Sometimes different packages require different versions of the same module.

This can lead to a situation where module A requires v1 of module C and module B requires v2 of module C. In this case, both versions of the same module C are installed in a tree like structure.

The order in which the dependencies are installed dictates this tree structure. For example, v1 of module C may get installed at the root level while v2 is installed as a nested dependency of module B.

The details behind how npm resolves dependencies is outside the scope of this article, but the package-lock.json file can help insure the exact tree is installed with subsequent installs.

npm install (with arguments)

npm install can be run with different arguments. Here are some of the more important ones to be aware of...

npm install (specified package)

npm install express

When npm install is run with a specified package argument, it installs the package in the existing node_modules directory.

You can optionally provide a specific version as well...

npm install express@4.16.4

When a version is not provided, npm automatically downloads the latest stable version.You can also specify several packages in the same command...

npm install express eslint mongo

This will install express, eslint, and mongo in a single command.

npm install (directory)

npm install myfolder

When a folder argument is specified, npm install downloads everything from the specified location to the original node_modules directory at the root of the project.

This assumes a myfolder sub-directory exists in the same location as package.json. Additionally, the myfolder has it's own package.json

npm install WILL NOT generate a new node_modules folder inside the sub-directory. Instead, the dependencies are hoisted to the root directory's node_modules folder.

npm install (from git)

npm install (with options)

In addition to arguments, npm install can be run with different options. Here are some of the more important ones to be aware of...

npm install (with --global)

npm install -g
npm install --global

When run with --global or -g, npm install installs the package globally. This means the package is installed in two places. The first is at the root directory where package.json is defined. The second is the global node_modules folder on the user system.

As a general rule, you want to install packages globally when they will be reused across projects or when they provide executable commands from the CLI.

npm install (with --save)

npm install express --save

When run with --save, npm install modifies the package.json file to include the specified package as a dependency. In this case, the express package will be added as a dependency to package.json.

The --save option is important whenever you want future installs to include the specified package.

npm install (with --save-dev)

The --save-dev flag specifies that the package should be added to the devDependencies section of the package.json rather than the dependencies section.



npm dependencies vs devDependencies

So what's the difference? Packages included as devDependencies won't get installed when the optional --production flag is used. This makes it possible to exclude packages you only need for development.

For example, linters are popular for enforcing clean code but aren't necessary in production. You would include a linter package as a devDependency so you can run linters against your code locally without including it in a production build.

npm install (with --production)

npm install -p
npm install --production

The --production flag specifies to exclude devDependencies from the install. This means any dependency listed under the devDependencies section of package.json won't get installed when this flag is present.

Your thoughts?

MakeMeCTO |

great read. some other things to note...

Order Precedence

The installation of the dependencies defined in package.json file are prioritized based on the presence of following files (in this order)

  1. npm-shrinkwrap.json
  2. package-lock.json:
  3. yarn.lock

Remember that package.json alone can define ranges of acceptable dependencies. While a package-lock.json file captures the exact versions of all dependencies in the tree, the npm-shrinkwrap.json file FORCES the exact use of these dependencies.

Definition of a "package" in npm

  • Any folder containing a package.json file is considered a package
  • Any zipped tarbell file containing a folder with a package.json
  • Existing packages published to npm registry
  • Tags of existing packages
  • GIT remote URLS that resolve to folderes with package.json files in them

The production flag

Specifying --production will not install devDependencies...

peerDependencies

The peerDependency ensures the same compatible version of a dependency is used.

If package A depends on package B and package B has a peer dependency on package C then package A better add C as a dependency...

semvar

Understanding semvar is important to understanding npm install in general :)

Enginears |

npm install works by installing all of the dependencies that you've declared in your package.json file.

Each dependency has it's own package.json file with it's own list of dependencies....npm install will install ALL of the nested dependencies as efficiently (or flat) as possible. If different dependencies have commonly shared sub dependencies, then a single version can be shared. However, if two modules rely on different versions of the same dependency, then both versions will be installed at different levels of the tree "hierarchy". This allows the reusable deps to be shared and keeps specific versions under the "one-offs" that need them.

MakeMeCTO |

great read! curious how this compares to other build tools like gradle and maven (java).

SherryAtkins |

npm install

this will install all of the NodeJs dependencies onto the target OS. It will pull from the Public npm registry unless an alternative registry is specified.

SwiftOverJava |

It's important to note that npm install won't install everything inside node_modules folder every time. It only installs when not found in tree of dependencies basically.

theRealJS |

this is a great cheat sheet. official docs are great obviously because they include everything you'd need..but this just tells you what you need to know about npm install so you can build something you're interested in...

TheRecursionExcursion |

While npm is a great build tool, there have been several issues with it from a security vulnerability standpoint. It's also messy when you have nested dependencies as builds can differ from one local machine to the next.

Obviously npm is huge though and will continue to be one of the most package managers to use with NodeJs and the NodeJs ecosystem.

Ariel Robaldo |

Great article!

Easy to read and direct to the point. A time saver.

Thanks!

Tom Edmonds |

great read very helpful...honestly more comprehensive than the actual docs :)

AMZ EMPLOYEE |

i still don't get peer dependencies..

MakeMeCTO |

is yarn any better? I hear yarn is the facebook version of npm. Are there significant differences or is this just splitting hairs?