Package manager wars. The real picture
Wojciech Maj
Posted on October 21, 2023
"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 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 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 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, 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 inpackage.json
. If present, count as whatever is specified. - Check for
package-lock.json
ornpm-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.
- Check if
And so, the script was born.
Without further ado, here are the results:
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:
Posted on October 21, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.