Think Before You npm install
- Run into a problem
- Find a node module through a quick Google search
npm installfor the module
- Write some code according to the module's docs
- Move on to the next problem
Often times, we add libraries to our projects to solve a problem without sufficiently evaluating the impact to our application. As I tell the teams I work with, once a module installed from
npm is included in an app, you're accepting ownership of that code in your project.
npm modules is a great way to get things done. They allow us to take advantage of solutions built by and debugged by the larger community. We can reach for them to solve specific problems that are outside of our core domains. There are a lot of benefits of the node ecosystem, but you need to make sure you're making an informed decision that you can ultimately accept responsibility for within your code base.
The first thing you should ask yourself, is if you need an external library at all.
For particularly tricky problems, I like to consider if the problem can be avoided entirely. Sometimes, if you dig a little deeper, you can re-frame the questions that led you to the module you're about to install and it turns out, there is a completely different approach that removes the problem entirely.
This doesn't always work, but it's worth taking a step back and at least considering it.
Sometimes, you'll find that you can solve the problem yourself by building a focused utility. You shouldn't feel the need to build everything yourself, but if you have a small enough or specific enough need, sometimes just writing some tests and code is enough.
You might also find that through sub-dependencies, you already have a module installed that serves your needs. Rather than installing a second solution to the same problem, you can just elevate that sub dependency to an explicit dependency of your project and use the module that is already getting bundled up with your code anyway.
If you've found a library that you think will meet your needs, keep looking. You should find a couple alternatives and then evaluate them all to determine the best choice for your project.
Once you've determined that an external dependency is the right call and you've found a few options to solve the problem at hand, now it's time to get down to the real work of evaluating each option.
You should consider each of the following questions for each library you're considering.
Since you likely have dependencies already, it's worth exploring your current bundle to see if one of your options is already being included in your production code. If so, you can add that module as an explicit project dependency and move on with your life.
If your option isn't already a sub-dependency that you can take advantage of, it's time to investigate how much it could impact your bundle size. For this, I reach for Bundlephobia. All you need to do is enter your package name in the search field and you'll get some metrics around the bundle size, both minified and minified & gzipped, along with approximate download times based on different network speeds.
Bundlephobia will also let you know if a library is tree-shakable, meaning dead code elimination will result in unused portions of the code being omitted from your production bundle.
Is this really the right tool for the job? Does it try to solve 100 problems when you only have one? If you'll only use a small subset of the library's available API, you should make sure it's tree-shakable so you don't end up shipping a lot of unused code in your production bundle.
On the flip-side of this, the API could fall short of what you need. If you end up having to write a lot of extra code to work around the library's short-comings, you might end up introducing more friction than you would with a more complete library or by writing all of the code in the first place.
- Are there recent commits?
- Is the issue count reasonably low?
- Are issues actively being discussed and closed out in a reasonable amount of time?
- Are maintainers responsive to external contributors?
- Is the README clear?
- Are there external docs?
- Is there a discord where this is actively discussed?
- Can you find answers to your questions?
- Is there information about different use cases, edge cases?
- How many downloads does it get?
- Are you aware of other teams and companies who make use of it?
- Is it used by projects you're aware of?
If you had to take over this code base to add features and fix bugs, would you feel comfortable working with it?
With all the information you've gathered from the above steps, now you can choose an option, knowing that you know what you're getting into from a long-term ownership perspective.
Not all the boxes need to be checked. Certainly, a simple utility shouldn't be removed from contention because it doesn't have a thriving community in discord, it is a simple utility after all. These are just possible data points. Your needs and the overall context of the problem will determine how important each specific data point is in making this particular decision.
Once you've chosen a direction, make sure you document the decision and share the rationale behind it. All the careful consideration and research will help answer that question for other devs who work in the code now and in the future. Documenting the decision will also save a few steps and provide a jumping off point for future decisions.