Understanding and Mastering Peer Dependencies in npm

Posted by Mohit Chavda 13 Jun, 2023 7 Min read
Understanding and Mastering Peer Dependencies in npm

I'm excited to share with you my journey of understanding and mastering peer dependencies in npm. As a developer, I've come to realize the significant impact that peerDependencies can have on the success of a library and the smooth functioning of an application.

During my exploration, I discovered that peerDependencies not only benefit library authors but also offer immense value to application developers like myself. By explicitly suggesting which dependencies should be installed or already present in the app, peerDependencies provide clear guidelines for seamless integration.

So, let's dive in together and uncover the power of peer dependencies in npm, gaining the knowledge and skills to enhance our development processes and build more robust applications.

Significance of PeerDependencies in npm

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 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 reacts in your app. YES, I am goddamn right!

If you are ok with 2 reacts 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

  1. the dependency size doubles. (for us, react's size doubles)
  2. the rules of hooks enforce to use of only 1 version of react in the app. (rule number 3 in the below image)
  3. 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.

Conclusion

I've realized the immense value of understanding and mastering peer dependencies in npm, both as a library author and an application developer. By leveraging peerDependencies, I can optimize dependency management, guarantee compatibility, and eliminate version conflicts in my projects.

Embracing the power of peer dependencies has transformed my npm workflow, allowing me to create more robust and efficient applications. I encourage you to explore and leverage peerDependencies in your own projects, experiencing the benefits firsthand.

Let's unlock the full potential of peer dependencies and take our npm development to new heights!

Subscribe to The Friday Brunch
Our twice a month newsletter featuring insights and tips on how to build better experiences for your customers
READ ALSO

Have a product idea?

Talk to our experts to see how you can turn it
into an engaging, sustainable digital product.

SCHEDULE A DISCOVERY MEETING