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.
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.
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
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.
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.
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.
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.
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.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!