Reputation: 47576
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.
Upvotes: 2967
Views: 1070972
Reputation: 6786
Something that was not mentionned yet: devDependencies
are useless if you don't publish the project manifest, but generate a package manifest instead. In this kind of context, the dependencies of the package are computed from the actual dependencies that your package depends on instead of the arbitrary list declared in the project manifest, and there is no need to distinguish between devDependencies
and dependencies
in the project manifest.
Some tools like Package Manifest Generator, rollup-plugin-generate-package-json or esbuild-plugin-package-manifest are dedicated to this purpose.
Upvotes: 0
Reputation: 1
It's really simple
In package.json there an dependencies object which contains all the dependencies with it's version number. you install it like,
npm install <packagename>
there is also an object called dev Dependencies which includes all the packages that are used in development phase not production or testing phase. you install these packages like,
npm install <packagename> --save-dev
dev dependencies may be needed at some point during the development phase, but not during execution.
examples webpack, rollup these are bundlers used to compile your app but they are not the part of your app.
I hope this answer will solve your doubts. Happy to help. keep growing.
Upvotes: -1
Reputation: 41
When using Webpack to bundle a frontend application, the distinction between dependencies and devDependencies is not so clear. For the final bundle, it doesn't matter where you place the dependencies (but it may be important for other tools). That's why the documentation seems confusing.
I found the explanation here: Do "dependencies" and "devDependencies" matter when using Webpack?
Upvotes: 3
Reputation: 382462
Summary of important behavior differences:
dependencies
are installed on both:
npm install
from a directory that contains package.json
npm install $package
on any other directorydevDependencies
are:
npm install
on a directory that contains package.json
, unless you pass the --production
flag (go upvote Gayan Charith's answer), or if the NODE_ENV=production
environment variable is setnpm install "$package"
on any other directory, unless you give it the --dev
option.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) This explains it nicely: https://flaviocopes.com/npm-peer-dependencies/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
is 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:
bundledDependencies
which is discussed on the following question: Advantages of bundledDependencies over normal dependencies in npmoptionalDependencies
(mentioned by Aidan Feldman)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.
(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:
grunt
is a peer-dependency
require('grunt')
is under 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 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.
Upvotes: 3288
Reputation: 20089
dependencies: packages that your project/package needs to work in production.
devDependencies: packages that your project/package needs to work while development but are not needed on production (eg: testing packages)
peerDependencies: packages that your project/package needs to work in tandem with (“colaborating” with them) or as a base, useful mainly when you are developing a plugin/component to let know with which version of the “main” package your plugin/component is supposed to work with (eg: React 16)
Upvotes: 7
Reputation: 24224
When trying to distribute an npm package you should avoid using dependencies
. Instead you need to consider adding it into peerDependencies
.
Most of the time dependencies are just a bunch of libraries that describes your ecosystem. Unless, you're really using a specific version of a library you should instead let the user choose whether or not to install that library and which version to choose by adding it into the peerDependencies.
Upvotes: 3
Reputation: 40448
There are some modules and packages only necessary for development, which are not needed in production. Like it says it in the documentation:
If someone is planning on downloading and using your module in their program, then they probably don't want or need to download and build the external test or documentation framework that you use. In this case, it's best to list these additional items in a devDependencies hash.
Upvotes: 48
Reputation: 17677
dependencies
Dependencies that your project needs to run, like a library that provides functions that you call from your code.
They are installed transitively (if A depends on B depends on C, npm install on A will install B and C).
Example: lodash: your project calls some lodash functions.
devDependencies
Dependencies you only need during development or releasing, like compilers that take your code and compile it into javascript, test frameworks or documentation generators.
They are not installed transitively (if A depends on B dev-depends on C, npm install on A will install B only).
Example: grunt: your project uses grunt to build itself.
peerDependencies
Dependencies that your project hooks into, or modifies, in the parent project, usually a plugin for some other library or tool. It is just intended to be a check, making sure that the parent project (project that will depend on your project) has a dependency on the project you hook into. So if you make a plugin C that adds functionality to library B, then someone making a project A will need to have a dependency on B if they have a dependency on C.
They are not installed (unless npm < 3), they are only checked for.
Example: grunt: your project adds functionality to grunt and can only be used on projects that use grunt.
This documentation explains peer dependencies really well: https://nodejs.org/en/blog/npm/peer-dependencies/
Also, the npm documentation has been improved over time, and now has better explanations of the different types of dependencies: https://github.com/npm/cli/blob/latest/docs/content/configuring-npm/package-json.md#devdependencies
Upvotes: 174
Reputation: 449
These are the packages that your package needs to run, so they will be installed when people run
npm install PACKAGE-NAME
An example would be if you used jQuery in your project. If someone doesn't have jQuery installed, then it wouldn't work. To save as a dependency, use
npm install --save
These are the dependencies that you use in development, but isn't needed when people are using it, so when people run npm install
, it won't install them since the are not necessary. For example, if you use mocha
to test, people don't need mocha
to run, so npm install
doesn't install it. To save as a dev dependency, use
npm install PACKAGE --save-dev
These can be used if you want to create and publish your own library so that it can be used as a dependency. For example, if you want your package to be used as a dependency in another project, then these will also be installed when someone installs the project which has your project as a dependency. Most of the time you won't use peer dependencies.
Upvotes: 5
Reputation: 17453
peerDependencies
didn't quite make sense for me until I read this snippet from a blog post on the topic Ciro mentioned above:
What [plugins] need is a way of expressing these “dependencies” between plugins and their host package. Some way of saying, “I only work when plugged in to version 1.2.x of my host package, so if you install me, be sure that it’s alongside a compatible host.” We call this relationship a peer dependency.
peerDependencies
are for plugins, libraries that require a "host" library to perform their function, but may have been written at a time before the latest version of the host was released.
That is, if I write PluginX v1
for HostLibraryX v3
and walk away, there's no guarantee PluginX v1
will work when HostLibraryX v4
(or even HostLibraryX v3.0.1
) is released.
From the point of view of the plugin, it only adds functions to the host library. I don't really "need" the host to add a dependency to a plugin, and plugins often don't literally depend on their host. If you don't have the host, the plugin harmlessly does nothing.
This means dependencies
isn't really the right concept for plugins.
Even worse, if my host was treated like a dependency, we'd end up in this situation that the same blog post mentions (edited a little to use this answer's made up host & plugin):
But now, [if we treat the contemporary version of HostLibraryX as a dependency for PluginX,] running
npm install
results in the unexpected dependency graph of├── [email protected] └─┬ [email protected] └── [email protected]
I’ll leave the subtle failures that come from the plugin using a different [HostLibraryX] API than the main application to your imagination.
... that's the whole point of plugins. Now if the host was nice enough to include dependency information for all of its plugins, that'd solve the problem, but that'd also introduce a huge new cultural problem: plugin management!
The whole point of plugins is that they can pair up anonymously. In a perfect world, having the host manage 'em all would be neat & tidy, but we're not going to require libraries herd cats.
Instead, we have the concept of being peers. Neither host nor plugin sits in the other's dependency bucket. Both live at the same level of the dependency graph.
If I'm PluginX v1
and expect a peer of (that is, have a peerDependency of) HostLibraryX v3
, I'll say so. If you've auto-upgraded to the latest HostLibraryX v4
(note that's version 4) AND have Plugin v1
installed, you need to know, right?
npm
can't manage this situation for me --
"Hey, I see you're using
PluginX v1
! I'm automatically downgradingHostLibraryX
from v4 to v3, kk?"
... or...
"Hey I see you're using
PluginX v1
. That expectsHostLibraryX v3
, which you've left in the dust during your last update. To be safe, I'm automatically uninstallingPlugin v1
!!1!
How about no, npm?!
So npm doesn't. It alerts you to the situation, and lets you figure out if HostLibraryX v4
is a suitable peer for Plugin v1
.
Good peerDependency
management in plugins will make this concept work more intuitively in practice. From the blog post, yet again...
One piece of advice: peer dependency requirements, unlike those for regular dependencies, should be lenient. You should not lock your peer dependencies down to specific patch versions. It would be really annoying if one Chai plugin peer-depended on Chai 1.4.1, while another depended on Chai 1.5.0, simply because the authors were lazy and didn’t spend the time figuring out the actual minimum version of Chai they are compatible with.
Upvotes: 32
Reputation: 529
I found a simple explanation.
Short Answer:
dependencies "...are those that your project really needs to be able to work in production."
devDependencies "...are those that you need during development."
peerDependencies "if you want to create and publish your own library so that it can be used as a dependency"
More details in this post: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies
Upvotes: 26
Reputation: 2120
In short
Dependencies - npm install <package> --save-prod
installs packages required by your application in production environment.
DevDependencies - npm install <package> --save-dev
installs
packages required only for local development and testing
Just typing npm install
installs all packages mentioned in the
package.json
so if you are working on your local computer just type npm install
and continue :)
Upvotes: 12
Reputation: 7501
If you do not want to install devDependencies you can use npm install --production
Upvotes: 650
Reputation: 21535
To save a package to package.json as dev dependencies:
npm install "$package" --save-dev
When you run npm install
it will install both devDependencies
and dependencies
. To avoid install devDependencies
run:
npm install --production
Upvotes: 84
Reputation: 585
I'd like to add to the answer my view on these dependencies explanations
dependencies
are used for direct usage in your codebase, things that usually end up in the production code, or chunks of codedevDependencies
are used for the build process, tools that help you manage how the end code will end up, third party test modules, (ex. webpack stuff)Upvotes: 21
Reputation: 1094
A simple explanation that made it more clear to me is:
When you deploy your app, modules in dependencies need to be installed or your app won't work. Modules in devDependencies don't need to be installed on the production server since you're not developing on that machine. link
Upvotes: 26
Reputation: 34327
As an example, mocha would normally be a devDependency, since testing isn't necessary in production, while express would be a dependency.
Upvotes: 154