How to Choose the Best JavaScript Library for Your React and Next Project?

How to Choose the Best JavaScript Library for Your React and Next Project?

Developing web application is hard and doing everything by hand would take too much time. Imagine building a complex application without framework NextJS, Vue or bundlers such as webpack.

Of course, one could do everything by hand and there are cases where it makes sense. However, I would challenge anyone to build an application (with login and database) only using vanilla JS. I wouldn’t take the challenge.

Using libraries is normal

As said before, using libraries is normal and is even a good practice. Developers don’t add value to a project by building a complex state management system. Implementing new features is where the value lies.

There are cases where building a lot of things by hand makes sense. There are some industries (banking, security, for example) where the stakes are too high to use a third-party code that isn’t audited. Even in those cases, you can still benefit from libraries. The code is open source, you can still read the docks and the code on GitHub and get a grasp on how they built the library.

Although libraries are recommended and can tremendously help reduce the development time, this doesn’t mean that you should start installing a dozen dependencies and run npm install without any consideration.

Not all libraries are made equal, and taking the first result on NPM JS is not always the best choice.

What could go wrong

Doing a poor choice can have some major impact in the future, and it’s best to do a bit of research before installing a new library.

Not type-safe

TypeScript is getting more and more traction. The new 4.9 versions offer many interesting features and see some performance improvements. This is a blessing for developers, but can be a curse for some libraries maintainers.

Building a type-safe library can result in a lot of code that is only used for type definition and making sure everything works as expected.

Source: Tanner Linsley

However, not having types from an unknown library is an issue. Maintaining a code is already hard enough, you don’t want to have to find out that updating a library breaks your application without knowing where or how.

Most popular libraries are now written in typescript or offer type definition, which mitigates this issue.

Future limitation

I cannot count the number of times I used a service or a library and found out that the new feature that needs to be implemented isn’t supported or will require a lot of work.

There are no perfect services, and you’ll always find some limitation. Anyone thinking otherwise (and I had cases where it happened) lacks technical knowledge.

The goal is to make sure that the library you decide to go for won’t be an issue, or that the offered features are sufficient for your use case. Better doing a bit more research and comparing libraries instead of jumping to the first result.

Poorly Optimized Code or Performance Hit

Having a small bundle is important. This means that the clients will have smaller files to download, resulting in faster navigation.

It’s easy to only test the application on an optical fiber connection in the comfort of your home or office, but that’s not necessarily where your customer will be. A sub one second load time on fiber could be a 10+ second loading on a 3G connection.

Although bundle size is not the only metrics, it indicates if the project is heavy or not. I have a whole article dedicated to this subject for NextJS projects:

How to easily reduce your NextJS bundle size by 30%?
Reducing your NextJS bundle by 30% is possible. Here are four ways to help you slim your project down!

In that article, I showed how different methods of importing Lodash results in very different bundle.

import _ from 'lodash' // 73.13kB (gzip 25.43 kB)
import {isEmpty as badIsEmpty} from 'lodash' // 73.14kB (gzip 25.43 kB)
import isEmpty from 'lodash/isEmpty' // 7.04 kB (gzip 2.26 kB)

That’s one example, but there are libraries that won’t offer this kind of optimization. In that case, you’ll have to work with a larger bundle without being able to do anything except removing the library.

Maintenance Time Increase

Maintaining a project up-to-date is an important task. Not only you can benefit from the latest features and optimization (and bugs) but you’ll also get security patches making sure you have a safer code.

Updating 10 dependencies is not the same as updating 30 dependencies. As the number of dependencies grows, so does the potential issues (and it’s exponential).

Some smaller updates won’t cause any issue, and others might require to change a lot of things in your code. The JavaScript ecosystem is in constant ebullition and breaking updates are not infrequent.

For example, NextJS 13 offers a completely new way to build applications (still in beta). The feature can be incrementally adopted, teams have time to move the code out of the page folder. It’s great to offer time to adapt, but this also means that there might be a time when the NextJS team decides to stop supporting the old method. This won’t happen anytime soon, but not starting to migrate once the feature is stable could be dangerous.

Subscribe to the newsletter to get new articles right in your inbox!

Subscribe to the newsletter

Security Vulnerabilities

Last but not least, using third-party code can be a huge security issue. We often recommend people not to download random files they get in their emails, but developers love to run npm install and add libraries to projects.

A security breach in NPM happened earlier this year. This meant that attackers were able to distribute malware in packages. Although rare, those kinds of attacks are the worst that can happen. Automatic CI/CD would get the new packages and the malware could spread automatically.

NPM security breaches are infrequent. You’re more likely to download a package from a developer without making sure that the code is safe. It’s true that having pre-written hooks for your Firebase auth is seducing, but is it something you want to delegate to a stranger?

Finally, using dependencies is only the tip of the iceberg. The dependencies you install will most likely use dependencies, and so on and so forth. This means that a library could introduce vulnerabilities not in their code, but in the libraries used by the library. That’s why many libraries (such as Zod) say they have zero dependencies, it’s reassuring to know they built everything themselves.

What to Consider Before Choosing a Library

I had the opportunity in the past to work with talented people on projects that ranged from small to mid-complexity. Most of those projects were built in NextJS and used a variety of libraries.

As projects grew, so did maintenance, and it was getting harder and harder to make sure everything worked correctly. This was due, in part, to the number of libraries used. I decided to trim down the libraries to make our life easier.

These exercises helped me see what libraries were useful and search for alternatives for the ones that were causing issues. Here are the criteria I was looking for when choosing a library.

1. Numbers of weekly downloads

This number is not very representative, since a package  can be downloaded thousands of times in CI/CD pipelines. However, it’s a quick metric and gives some insights.

I wouldn’t go for a package with only a handful of weekly downloads. Instead, I would change my search query to NPMJS or search on Google for tutorials that solve the issue I’m trying to solve. Broadening the search by being less specific can lead to articles not using the same keywords. This allows discovering packages that would not have been discovered otherwise.

json-object-mapper on the left vs zod on the right. Which package would you choose?

2. State of the GitHub

Checking the numbers of weekly downloads is fine, but isn’t very representative. Looking at the state of the GitHub offers way more insights on how the project is maintained and run.

I had cases where a package I wanted to use wasn’t maintained anymore and the README on NPMJS wasn’t very clear about it. By looking at the GitHub, I saw that the repo was archived, I found an alternative with active support instead.

There are many metrics you can look at while looking at the GitHub. I tend to look at the number of stars, the number of openers issues and merges request and the number of contributors. All this information gives insights on the health of the project.

Finally, I often go to the release page and look that the date of the last release and the change log. This is a great way to see how often the library is updated and if the change logs are extensive enough when breaking changes are introduced.

Again, json-object-mapper on the left and zod on the right

3. Quality of the documentation

Once the GitHub is reassuring, it’s worth taking sometimes to look at the documentation. A README file can be plenty sufficient, but having a separate documentation website is a reassuring thing.

Since those libraries are meant for developers, it’s important that the documentation explains how the code works and what are the things that can be done with the library.

Good documentation has a quick start guide, explanation about components or methods it offers and some information about the error it could throw.

Here is an example of a beautiful and extensive documentation

4. Implementation caveats

Speaking of documentation, it’s always worth checking the « Quick Start » guide before downloading it.

There are a few things to consider in this guide. There are some signs that would make me consider the choice. For example, if the library requires you to change some typescript rules or install another library to make everything work.

Hopefully, the quick start guide should be small and pretty straightforward. If that’s not the case, it’s possible that the library is either very specific, in that cast it can be alright to do the efforts. But if the library solves more generic problems, it can be a sign that a better option exists somewhere else.

There is something strange for the React calendar libraries. I don’t know why, but most of the libraries demand to import a CSS file on the file where you intend to use the calendar. I cannot explain why it’s the case for most libraries, but you might have to bite the bullet if you end up using such a library.

import React from 'react';

import { format } from 'date-fns';
import { DayPicker } from 'react-day-picker';
import 'react-day-picker/dist/style.css';

export default function Example() {
  const [selected, setSelected] = React.useState<Date>();

  let footer = <p>Please pick a day.</p>;
  if (selected) {
    footer = <p>You picked {format(selected, 'PP')}.</p>;
  return (
An example of a calendar required CSS file

5. Size of the library

I like small bundles, I find quite exciting to do some optimization to ensure a small bundle and to have a good Lighthouse score. Sure, customers might not feel the improvements (this is somewhat wrong since the fast website on Wi-Fi can be very slow on mobile) but Google will rank your website depending on your web vitals score. Once a given threshold is reached,  improving performances is more important for Google and SEO than it is for end users.

It would be a shame to obliterate your efforts by poorly using a library, as it can be the case for lodash, or by using a library that will weigh your bundle down.

That’s why a website like bundlephobia give some insights on how heavy a library is. It’s also important to keep in mind that the number display on the top of the page represents the whole package, but tree shaking helps reduce the size of the library.

This seems huge, but date-fns has excellent tree shaking and won't weight that much

There are more details at the bottom of each page where you can see how much each export weights. This can be a bit more interesting than the total size of the package.

You can see for date-fns the size of every method of the package

6. Google search results

Last but not least, it’s great to find a maintained library that has a great doc, is optimized and is easy to work with. It’s also great to see if other people write about the library and share examples.

This indicates two things. First, you might find people facing the same issue you might have in the future. Then it shows that the library is somewhat adopted and people use it in the real life.

It’s great to know that you’re not the alone and that people might be able to help you if you face an issue.

Wrap up

You know the process I follow when I choose a library. You’ll be able to find the perfect library for your next project and can be a bit more confident about your choice.

I recently wrote an article that gives a list of libraries I used on most of my project. You can find the article here:

8 Amazing NextJS Libraries That Make Coding Easier
8 amazing NextJS libraries (with 4 bonus) that will make your life easier and your web application better!