node.jsnpmdependenciespackage.json

What's the difference between dependencies, devDependencies, and peerDependencies in NPM package.json file?


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?

Also added peerDependencies, which is closely related and might cause confusion.


Solution

  • Summary of important behavior differences:

    Related options not discussed here:

    devDependencies

    dependencies are required to run, devDependencies only to develop, e.g.: unit tests, CoffeeScript to JavaScript transpilation, minification, ...

    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:

    npm install
    

    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: dependencies.

    If you really want to install development packages in that case, you can set the dev configuration 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.

    peerDependencies

    (Tested before 3.0)

    Source: https://nodejs.org/en/blog/npm/peer-dependencies/

    With regular dependencies, you can have multiple versions of the dependency: it's simply installed inside the node_modules of the dependency.

    E.g. if dependency1 and 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:

    E.g. if dependency1 and 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 package.json file.

    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:

    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.

    Manual

    I think the documentation answers the question quite well, maybe you are just not 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 parameter. See npm-config(7) for more on the topic.

    And then under npm-config(7) find dev:

    Default: false
    Type: Boolean
    
    Install dev-dependencies along with packages.