Pnpm vs Npm vs Yarn - What to Choose?
Pnpm vs Npm vs Yarn - What to Choose?

In this post we will look on such package manager which is called Pnpm and compare it with Yarn and Npm.

Motivation

Here I opened the official website of Pnpm and you can directly see the motivation of creating another package manager. And actually as always when we talk about package managers we talk about speed of installation, correct way to cache them and saving disk space.

Pnpm tries to improve all this points and be better than Npm and Yarn.

If we are talking about free space this is entirely true. Npm and Yarn both take lots of space when they cache all modules.

Every single time when we install a dependency of dependency it creates a new copy.

Yarn / Npm have flat structure of all modules and them copy dependencies all the time

Pnpm leverages soft links and hard links to take less space and install everything faster

node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    │           ├── index.js
    │           └── package.json
    └── foo@1.0.0
        └── node_modules
            └── foo -> <store>/foo
                ├── index.js
                └── package.json

Here is a great example how Pnpm works. We have 2 packages foo@1.0.0 and bar@1.0.0 which is a dependency of foo package. As you can see both packages are not installed in root of node_modules but in .pnpm directory.

The next step is that our foo dependency will be symlinked to our bar dependency.

node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    └── foo@1.0.0
        └── node_modules
            ├── foo -> <store>/foo
            └── bar -> ../../bar@1.0.0/node_modules/bar

Which means this step resolves dependencies between packages by adding symlinks.

And the last step is to symlink the direct dependencies of our project in the root folder of node_modules.

node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    └── foo@1.0.0
        └── node_modules
            ├── foo -> <store>/foo
            └── bar -> ../../bar@1.0.0/node_modules/bar

In Pnpm the standard node_modules system works in exactly the same way as in other package managers.

Real example

Now let's look on the real example to check how Pnpm works. Here I generated create-react-app application.

Real project

Here is how our project looks like. We have a list of users and we can add new user. Our goal now is to migrate this project to Pnpm.

Inside our project we have package.json and package-lock.json. Just to remind you we need a lock file to lock correctly dependencies of dependencies.

If we look inside our node_modules folder you can see a flat list of hundreds of our dependencies. And they are all flat.

Now we need to install Pnpm on our machine. There are different ways to do that but the easiest is by using npm

npm i -g pnpm

What most people will do is just remove package-lock.json and run pnpm install. The main problem of this approach is that we disregard our lock file completely and create lock file from scratch.

It can break you project because some packages will be updated.

This is why we want to migrate from Npm or Yarn to Pnpm and there is a specific commands for that.

pnpm import

It created a pnpm-lock.yaml file of pnpm by reading package-lock.json file. Now we can safely remove package-lock.json and just use Pnpm,

Let's remove our node_modules completely and install all our dependencies with Pnpm

pnpm install

Pnpm install

Now inside node_modules we have packages which are dependencies of our project. No nested dependencies anymore. Inside node_modules/.pnpm we can see all our dependencies with symlinks between them.

And after I restart the project everything is working out of the box without and changes.

Real project

Is it faster?

And the last question is it really much faster than Yarn and Npm or not? For ordinary developer it doesn't matter what is the structure inside node_modules or how it all works. He wants fast and reliable system.

In the official website of Pnpm there are benchmarks that compare different package managers. And actually I thought that Pnpm will be a bit biased because they publish benchmarks on their website and they want Pnpm to look good. But if we check this benchmarks I don't see a huge difference between all three package managers.

Benchmarks

As you can see here we have different ways of installation. But essentially in every day work we have just 2 variants. It's either we never installed anything and we need to download, cache and install everything or we already installed and cached all packages and we just install them again.

Initial installation

This is our initial installation just we pulled project without anything. We have 15s, 16s, 10s. Realistically between Pnpm and Npm I don't see that much difference.

Already installed

Here we already have cache and installed packages. In this case it's 2s, 1.2s, 1.9s. Obviously inside a huge project this numbers will be bigger but it doesn't make such a huge difference.

Also I heard from some developers that they have less bugs with Pnpm compared to Yarn and Npm. But from my experience I didn't see any significant problems.

And actually if you are interested to learn how to create a full stack application with Socket IO, Typescript, Node, MongoDB and Angular make sure to check my Build Fullstack Trello clone: WebSocket, Socket IO course.