react-dom for your UI,
lodash for utility helper methods,
rollup as your bundler, and
@testing-library/react for unit tests.
All of these packages are stored as dependencies in your
package.json file. Understanding whether to include them as
peerDependencies can sometimes be a struggle for newer developers.
In this article we'll look at the three types of dependencies found in the
package.json file and what each does.
dependencies are packages used in your app's production bundle. If you're building a React app, then
react-dom would be dependencies. If you're using
react-router for client-side routing, that would also be part of your
dependencies. Any other packages like
lodash or a design system library like Material UI (
@mui/material) would also be
There is an exception to this rule, but we'll cover this down in the Peer Dependencies section below.
devDependencies are typically the tooling you use to build your project, but they're not actually included in the app's production bundle. For example,
rollup would both be
devDependencies. These are bundlers used to compile your app, but they're not part of your app.
The same goes for test frameworks and libraries like
jasmine. These libraries are needed for writing unit tests for your code, but they're not part of your production app.
Linters and code formatters like
lint-staged would all be
devDependencies as well.
peerDependencies are dependencies that your app relies on but expects another package to provide.
peerDependencies are a crucial tool in reducing the size of your final production app. Let's take a look at why.
Imagine that you have a large React app composed of many npm packages. Let's say there are 20 of them and they all use React. If each of these packages lists
react-dom in their
dependencies section, then that means you'll have 20 copies of React in your app! (21 if you count the copy that your main parent app provides as well.)
In order to avoid this massive bloat of dependencies, library developers can instead use the
peerDependencies section to specify that their library depends on
react-dom, but the consumer of the package needs to be the one to provide it. In doing so, you can then have your app with 20 dependencies but only have one copy of
react-dom used in production provided in the
dependencies in the
package.json file of your parent app.
peerDependencies, it's important to note that if you mark a package as a peer dependency, you also must include it in your
devDependencies section. This allows your app to install and use packages like
react-dom during local development and unit testing, but it won't include them as real dependencies in the production build.
Finally, when using a peer/dev dependency combination, you also should add the package in the
externals configuration section of your Webpack or Rollup config file.
Thanks for reading!