Package Managers Comparison: Yarn, NPM, PNPM

Yarn, NPM and PNPM are package managers from the JavaScript world. Everyone who downloads Node.js has NPM, so it's the most commonly used, yarn was created by Meta and PNPM is the newest and fastest. Here’s a detailed look at them.

Advantages and Disadvantages of NPM (Node Package Manager)

NPM is the default package manager for Node.js, it’s simple to use, and tends to run with few issues. Because of its default nature, NPM has amassed a robust community of users that can be a great use should you run into any issues. Although largely problem free, NPM does have some disadvantages. 

Sequential installation certainly falls into the disadvantages category - packages are installed sequentially, which increases installation time. Another disadvantage is the NPM audit. For a good rundown of the issues with this, check out this piece, NPM Audit: Broken by Design, on the overreacted site. In short, you may get critical errors during installation that scare you, but the critical error might be that a would-be attacker could have full access to your computer. If this is really an issue, you likely have a whole different set of (much more severe) problems. 

Advantages and disadvantages of yarn

Yarn's downloads are solved in parallel, making it much faster. It offers an out-of-the-box offline mode, which is nice when your internet goes down, and the plug-n-play feature tends to be quite useful. 

It’s no mystery that node_modules are the heaviest objects in the universe, but maybe it doesn’t have to be that way. 

Using hoisting in Yarn

With Yarn, Meta has made a pretty good attempt at solving some key problems with managing node modules. Packages are usually huge and take a long time to copy, delete, or otherwise manipulate. The problem arises when a package has other dependencies, and those in turn have other dependencies and so on, making the dependency tree unnecessarily deep. Sometimes, duplicate versions of the same packages can occur. To avoid this, Yarn uses a technique called hoisting.

Hoisting spreads common packages as far up the tree as possible so other packages can share them as well, thus eliminating the need to do so much downloading and copying. However, this has an interesting drawback - you might accidentally import a function from a subpackage that was installed by the library you were using, not by you. Most modern IDEs catch this, but it’s worth looking into.

Another potential downside is that hoisting uses semver, and this can lead to problems if any of the packages use it incorrectly. For example, it will mark a major change (major change X.x.x) that breaks the same compatibility as a minor change (minor change x.X.x). Yarn, unaware that something might break, then downloads that version and the problem is gone. This is often mentioned on Github for problem packages.

That's why Yarn came up with Plug'n'Play (PnP). PnP eliminates the node_modules folder, storing everything in a global directory. In the project we only have a .pnp.cjs that contains the links (explained below), and a PnP loader that tells you how to load them. This allows us to share between several projects, so we don't have to download and install over and over again. For example, if you have a lot of projects in Next.js, you don't want to download it again. PnP maintains one installation globally.

The Yarn Plug'n'Play implementation uses so-called symlinks, i.e. native links to files. There are two types:

  1. A soft link that becomes non-functional when moving the file
  2. A hard link that maintains the link even after the file is moved.

It’s important to point out that Yarn PnP doesn't work on all packages, which can be tricky. You’ll inevitably say to yourself: "React Native, it's actually a very big package, a piece, a huge library, I'll use PnP." But this doesn't work because React Native uses its own Metro builder that uses symlinks.

If you don't want to use PnP, you can set the node-linker mode in the configuration file and you will also get the aforementioned advantages, including speed.

Advantages and disadvantages of PNPM (Performant NPM)

PNPM is the newest and fastest package manager. It works quite similarly to Yarn's PnP in that it also uses symlinks. What's pretty cool is that it doesn't download entire packages, only the differences between versions. So I don't have to download the whole library.

Another nice feature is that when you use PNPM it will tell you in the console how many packages you're reusing and how much disk space you've saved, so if recycling is your thing, you’ll like this feature.

PNPM has the same drawback as PnP - namely that it may not support all packages.

The node_modules structure of PNPM is easy to read and nicely done - what's a package, what's a link (see image above), etc, is all quite clear. 

Package manager speed comparison

The graph below shows that NPM is usually the slowest. Interestingly, although Yarn PnP and PNMP use similar technology, there are some clear differences in speed.

The source of the chart is directly from the PNP"M site, so there can certainly be some bias. The measurement takes place every day, and you can always look at the current measurement and its methodology.

Experimental Node.js Features: CorePack

CorePack turns on in the console and aims to eliminate the need to install Yarn or PNPM. Node.js recognizes in package.json which package manager is defined - a huge relief that is built in from version 16.9.0. It's an experimental feature, but it's easy to run. I would also add that writing is longer with CorePack. Instead of writing “yarn add foo,” it’s necessary to add “corepack yarn add foo” to the beginning, although it can be shortened by aliases in some cases.

Is there a winner?

Let's sum it up. NPM is slower, but its creators are trying to improve it and it is catching up to the competition, but sequential downloads remain a core problem.

PNPM and Yarn PnP are fast, but their implementation can be problematic at times. I think Yarn is still “in,” and so far I haven't encountered any major problems using it.

And what about you? Which package manager wins for you? Let me know at tomas.veprek[at]cookielab.io.

Package Managers Comparison: Yarn, NPM, PNPM
Tomáš Vepřek
Frontend Developer
By clicking “Accept”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.