This documentation answers my question very poorly. I didn't understand those explanations. Can someone say in simpler words? Maybe with examples if it's hard to choose simple words?
EDIT also added
Summary of important behavior differences:
dependencies are installed on both:
npm installfrom a directory that contains
npm install $packageon any other directory
npm installon a directory that contains
package.json, unless you pass the
--productionflag (go upvote Gayan Charith's answer).
npm install "$package"on any other directory, unless you give it the
npm install, and you have to solve the dependency yourself manually. When running, if the dependency is missing, you get an error (mentioned by @nextgentech)
Transitivity (mentioned by Ben Hutchison):
dependencies are installed transitively: if A requires B, and B requires C, then C gets installed, otherwise B could not work, and neither would A.
devDependencies are not installed transitively. E.g. we don't need to test B to test A, so B's testing dependencies can be left out.
Related options not discussed here:
bundledDependencieswhich is discussed on the following question: Advantages of bundledDependencies over normal dependencies in NPM
optionalDependencies(mentioned by Aidan Feldman)
dependencies are required to run,
If you are going to develop a package, you download it (e.g. via
git clone), go to its root which contains
package.json, and run:
Since you have the actual source, it is clear that you want to develop it, so by default both
dependencies (since you must of course run to develop) and
devDependency dependencies are also installed.
If however you are only an end user who just wants to install a package to use it, you will do from any directory:
npm install "$package"
In that case, you normally don't want the development dependencies, so you just get what is needed to use the package:
If you really want to install development packages in that case, you can set the
dev config option to
true, possibly from the command line as:
npm install "$package" --dev
The option is
false by default since this is a much less common case.
(tested before 3.0)
With regular dependencies, you can have multiple versions of the dependency: it's simply installed inside the
node_modules of the dependency.
dependency2 both depend on
dependency3 at different versions the project tree will look like:
root/node_modules/ | +- dependency1/node_modules/ | | | +- dependency3 v1.0/ | | +- dependency2/node_modules/ | +- dependency3 v2.0/
Plugins however are packages that normally don't require the other package, which is called the host in this context. Instead:
dependency2 peer depend on
dependency3, the project tree will look like:
root/node_modules/ | +- dependency1/ | +- dependency2/ | +- dependency3 v1.0/
This happens even though you never mention
dependency3 in your
I think this is an instance of the Inversion of Control design pattern.
A prototypical example of peer dependencies is Grunt, the host, and its plugins.
For example, on a Grunt plugin like https://github.com/gruntjs/grunt-contrib-uglify, you will see that:
tests/: it's not actually used by the program.
Then, when the user will use a plugin, he will implicitly require the plugin from the
Gruntfile by adding a
grunt.loadNpmTasks('grunt-contrib-uglify') line, but it's
grunt that the user will call directly.
This would not work then if each plugin required a different Grunt version.
I think the doc answers the question quite well, maybe you are not just familiar enough with node / other package managers. I probably only understand it because I know a bit about Ruby bundler.
The key line is:
These things will be installed when doing npm link or npm install from the root of a package, and can be managed like any other npm configuration param. See npm-config(7) for more on the topic.
And then under npm-config(7) find
Default: false Type: Boolean Install dev-dependencies along with packages.