Package manager wars. The real picture
Tags: npm, yarn, pnpm, javascript
Published: 2023-10-21 22:37:03

---
title: Package manager wars. The real picture
published: true
description: npm, Yarn or pnpm? Which package manager is ACTUALLY more popular?
tags: npm, yarn, pnpm, javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4cm69p0vlkk9ofsrcyg.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-10-21 18:20 +0000
---
"pnpm has surpassed Yarn!" I've read on Twitter the other day. _"In what exactly?"_ - I thought to myself. The answer to this question turned out to be: _"In npm downloads"_. However, this doesn't mean anything at all!

In this article, we'll explore why it's a horrible way of comparing different package managers popularity, and we'll find out the real answer to the question: "Which package managers are the most popular?".

### Why npm downloads can't be counted?

The most obvious problem with counting npm downloads is that **npm ships with Node.js**. This means that, in theory, everyone can use npm in Node.js project with no additional downloads. You don't _download npm from npm_ to obtain it, only to update it. 

### Why Yarn downloads can't be counted?

First, I need you to know that Yarn Classic (v1) and Yarn Modern (also known as Yarn Berry; v2+) are completely different things.

#### Let's look at Yarn Classic first.

Yarn Classic was indeed shipped as an npm package called `yarn`. The recommended way of installing it was by running `npm install -g yarn`. However, **it is not the only way of downloading Yarn Classic**. Among many others you could use `brew`, [config of which](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/y/yarn.rb) unveils that, unsurprisingly, it downloads Yarn binary from yarnpkg.com rather than npm.

#### For Yarn Modern, things got complicated.

Before Corepack (I'll cover it later) became a thing, Yarn 2 installation was _weeeird_. To install Yarn 2, you had to install Yarn 1 first. Then, _in every repository_, you had to run `yarn set version berry`, which installed Yarn 2 _in this repository_, specifically in `.yarn/releases`. While doing so, you could see the console output:

```
Resolving berry to a url...
Downloading https://github.com/yarnpkg/berry/raw/master/packages/berry-cli/bin/berry.js...
Saving it into /private/tmp/my-app/.yarn/releases/yarn-berry.js...
Updating /private/tmp/my-app/.yarnrc...
Done!
```

So, again, _not npm_. In fact, **you cannot download Modern Yarn from npm at all!**

#### Corepack

Nowadays, the recommended way of installing Yarn is through Corepack, a tool shipped (although not _enabled_ - yet) by default with Node.js.

Slight off-topic: I highly recommend you to familiarize yourself with Corepack, regardless of your package manager of choice. Once enabled, it transparently downloads a binary for a package manager a given project requires, as specified in `packageManager` in `package.json`. You don't need to install Yarn or pnpm manually at all!

Back to the topic. Where does Corepack downloads Yarn from? [Corepack's config](https://github.com/nodejs/corepack/blob/0bd2577bb4c6c3a5a33ecdb3b6ca2ff244c54f28/config.json#L131-L152) makes it clear: it's yarnpkg.com, so again, **not npm**.

### Why pnpm downloads can't be counted?

pnpm's 1st (and thus preferred) installation method [installation instructions](https://pnpm.io/installation) is "Using standalone script". Looking at script source, we quickly learn it downloads its binaries from GitHub. So… **not npm**.

Unlike Yarn, pnpm _can_ actually be downloaded from npm. Corepack [takes advantage of that](https://github.com/nodejs/corepack/blob/0bd2577bb4c6c3a5a33ecdb3b6ca2ff244c54f28/config.json#L79-L95), and uses npm under the hood to download pnpm binaries.

### What do we know so far?

* npm is underreported on npm downloads stats. You don't need to download it to use it.
* Yarn Classic is underreported. You can download it from other sources.
* **Yarn Modern is not reported at all**. You can't download it from npm.
* pnpm is underreported. You can download it from other sources.
* **And perhaps the most importantly, more npm downloads != more popularity**. It just means… There is more downloads. If package manager A is updated weekly, and package manager B is updated once per year, A will get more downloads than B, even if B is technically more popular.

### So what can we measure?

Here's my plan.

* Get as many most starred GitHub JavaScript and TypeScript repositories as I can.
* Figure out package manager each repo is using.
  * Check if `packageManager` is present in `package.json`. If present, count as whatever is specified.
  * Check for `package-lock.json` or `npm-shrinkwrap.json`. If present, count as npm.
  * Check for `yarn.lock`, and…
    * Check for `.yarnrc.yml`. If present, count as Yarn Modern.
    * If not, count as Yarn Classic.
  * Check for `pnpm-lock.yaml`. If present, count as pnpm.
  * Check for `bun.lockb`. If present, count as Bun.
  * If all else fails, check documentation for commands that would hint on package manager used.

### And so, the script was born.

Without further ado, here are the results:

![Pie chart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/399h3plfdh5kds2t5heo.png)

|Package manager|Total|
|---|---|
|npm|978 (53%)|
|Yarn Classic|471 (26%)|
|Yarn Modern|75 (4%)|
|pnpm|105 (6%)|
|Bun|4 (0%)|
|unknown|203 (11%)|

|Stat|Total|
|---|---|
|Projects examined|2040|
|Projects with `package.json`|1836|
|Projects using Corepack|179|
|Projects not using Corepack, but with a lockfile|1657|

So there you have it. The real picture of package manager wars. 

pnpm does, indeed, appear to have surpassed Yarn Modern (v2 and v3). But it is nowhere near to Yarn Classic's (v1) popularity, which, in turn, is not nearly as popular as npm.

npm is the absolute king with whopping 53% of the "market". In reality, it's likely even more than that. 11% of the projects examined did not have lockfile committed. My suspicion is that the vast majority of maintainers of these projects are in fact using npm, as there is no (machine-readable) indication that something other than the "default" is being used.

### Final words

If you'd like to see how the script was done, or would like to improve it, please visit:

https://github.com/wojtekmaj/package-manager-stats