Understading and Mastering Peer Dependencies in npm
An in-depth tutorial for managing your npm dependencies like a pro
Table of contents
So, peerDependencies
are the dependencies generally mentioned in libraries' package.json which suggest to the library users, that they should install these dependencies explicitly (or have already installed these dependencies) in their app, to use this library.
Before starting, I want to say, these are not just helpful to library authors, but also to many application developers as well. And, don't forget to visit the Advanced Usage section at the end, where I have mentioned a specific usecase for our app.
The Problem
Let us understand, there is an awesome library called react-datepicker ..... now to use this library, your project should have react as a dependency (and also react-dom). Now, how does the library author communicate this to every user? And definitely, just prefixing the library name with 'react' is not the solution ;-). So what do they do? (They read Mohit's blog to know about this powerful field in package.json which is peerDependencies
) So, they put all these dependencies in peerDependencies.
You must be asking, why not just put it in dependencies
field? why bother knowing peerDependencies
.
Well, let me raise a situation to explain how npm works. Let us suppose a library author of react-datepicker, decided to add react and react-dom as dependencies in the project. Now, here they must be putting a particular version of react and react-dom, right? Now, imagine thousands of users who are going to use the library. Do you think, they must be using the same version of react and react-dom? Obviously no. Also, on the other hand, all the users' apps, definitely will have many libraries, like react-datepicker and hence more diff versions of react.
There might be even the smallest version difference (lib's react v16.9.0 and your app's react v16.9.1) between lib's dependency version of react and your app's version of react. So, anyway, what happens in this scenario? So, you might be surprised to know, that our beloved npm, will install 2 react
s in your app. YES, I am goddamn right!
If you are ok with 2 react
s in the app, then this article is not for you. ;-)
So, react is just an example. This is a very generic problem for any npm library author and users both.
The problem in the example actually has 3 problems
the dependency size doubles. (for us, react's size doubles)
the rules of hooks enforce to use of only 1 version of react in the app. (rule number 3 in the below image)
the library might be only working with some specific set of react version (the standard example is >v16.8, because some libraries might be using hooks that only works with >v16.8) and we don't want users to install our library who are still using older than 16.8 version
our #2 problem indicates a specific react problem, but I believe, if a library is running a side effect, and that side effect has contradictory working functionalities between their 2 diff. versions, it might be the same issue as our react.
Now, let us try to understand 1 important aspect of the problem, before moving towards a solution. Technically, our library can run for multiple versions of React. be it 16.9.0, 16.9.1 ( and in fact, even for 17.x.x versions).
The Answer
To tackle this, we have peerDependencies
. So, When you put a list of dependencies under the field peerDependencies
for your library, and when your user runs npm install {your-library}
script, it won't install these peerDependencies
explicitly.
Now, after installation, your library's components will use the package react, but not from the library's bundle (or node_modules. {which will consist only of dependencies
and not peerDependencies
}), but from the app's bundle (or node_modules). Hence, there are no 2 copies of react in your app. Also, we have mentioned a specific version of react.
So, if a user with lesser than 16.8.0 version of react or greater than or equal to v18.0.0 (because our library works with only less than v18.0.0), try to install the library, they will get the following error while doing npm install
and they will know that they can't use this library with the current react version.
💡Remember, that for the library authors, in the development mode, they still need react and react-dom, so they have to add all the peerDependencies
in their devDependencies
to use them while writing code.
This above scenario teaches us, that peerDependencies
are not considered to be installed while any npm install script runs(be it library's or app's npm install), but rather, they are used as an acknowledgement to the user, when they are unavailable (technically unmet) in the user's app's package.json file folder.
Advanced Usage
How I have made use of peerDependencies
in 1 of our large scale apps?
We have our custom private UI library in 1 of our projects. It has 6 to 7 different React apps which are using the private UI library.
Now, our library has a few components written from scratch and a few HOCs from well-renowned libraries like lodash, react-select, react-datepicker, date-fns, react-toasify.
Now, our UI library also uses these libraries, and we don't want to enforce a particular version of these libraries on every app of ours, because our apps, might be using these libraries directly and not from our UI library. Because,
1. we have created HOCs of these libraries, for the components we most use
2. for libraries like lodash and date-fns, it is very obvious that we have used it in our library as well as in our app
So, we don't want multiple versions of these libraries in our app, just because our private UI library is using it. So, we have added all these libraries in package.json's peerDependencies
and each of our app run exactly 1 instance of these libraries so we don't have to worry about multiple version and compatibility issues we could have run into.