Why you should prefer using pnpm ?
Tags: javascript, programming, webdev, devops
Published: 2022-10-13 12:23:06

**Author: <a  target="_blank" href="https://refine.dev/blog/author/muhammad_khabbab/">Muhammad Khabbab</a>**

## Introduction
A package manager is responsible for installing, updating, and removing software packages and dependencies. NPM has been widely used as the standard package manager for Javascript; however, companies are quickly adopting the pnpm package manager due to its immense benefits.  

Steps we'll cover:
- [What is pnpm?](#what-is-pnpm)
- [Why not npm or yarn?](#why-not-npm-or-yarn)
- [How does pnpm solve these problems?](#how-does-pnpm-solve-these-problems)
- [Advantages of pnpm](#advantages-of-pnpm)
	- [Disk space efficiency](#disk-space-efficiency)
	- [Improved speed](#improved-speed)
	- [Security](#security)
- [pnpm CLI](#pnpm-cli)
- [Migrating from NPM/Yarn to PNPM](#migrating-from-npmyarn-to-pnpm)

## What is pnpm?
**pnpm** is a drop-in replacement for npm. It is built on top of npm and is much faster and more efficient than its predecessor. It is highly disk efficient and solves inherent issues in npm. In this article, we will discuss pnpm in detail. We will explain how it works and will go through why **pnpm** is a perfect replacement for npm or yarn. 

Let’s start with discussing the issues in existing package managers. 

## Why not npm or yarn?
Npm uses flattened `node_modules`. The flattened dependency results in many issues, such as:
1.	The algorithm for flattening a dependency tree is complex
2.	Some of the packages have to be duplicated inside another project’s `node_modules` folder
3.	Modules have access to packages they do not depend on

Let’s explain this with a basic example. One of your projects needs an express module, and express has a dependency package named “debug”. This is how the structure of node modules will look like:


![Image dependecies](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ui4g3mtyjgjm6v9svhq.png)
<em> Figure 1 - Example project dependencies</em>





Your code can `require('debug')`, even if you do not depend on it explicitly in the `package.json` file. Let’s discuss two scenarios that can cause issues:

1.	Express updates its debug dependency with breaking changes.
2.	Express does not depend on debug anymore.

In both cases, your code will fail because it has an implicit dependency to debug. That is a big problem. Similarly, if you work with a large monorepo, then it will be much more difficult to track particular dependencies a project uses. Duplicate packages are another issue here. Now yarn is slightly better in terms of optimizing disk space as it makes use of hoistings; however that approach fails in some cases. 

## How does pnpm solve these problems?
**pnpm** uses hard links and symlinks to maintain a semistrict `node_modules` structure. So what’s the difference between a hard link and a soft link? Well, a hard link is a different reference to the same file. In soft link, you create a new file, and the contents of the file point to another path. Symlinks are symbolic links that pnpm uses to create a nested structure of dependencies.  
Let’s see the pnpm version of the express and node modules discussed in the previous section. 

<br/>



![Image structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sukrl2lxp005exauf9zh.png)
	<em> Figure 2 - project structure with pnpm</em>


The above picture shows the directory structure of your project files. The first thing you will notice is that your code cannot access the “debug” package because it is not directly under the root level `node_modules` directory. pnpm has created a special folder named “.pnpm” that contains hard links to all the modules.  

If you look at `express/4.0.0`, the `express` module is a hard link to the global `pnpm-store` and a `debug` symbolic link to the debug hard link that also links to the global pnpm-store. 

 Below is the image of the actual pnpm-store, which contains the packages. This is where all the downloaded dependencies are maintained. When you download a dependency, pnpm first checks whether the dependency is present in this store or not. If it finds the dependency in the store, pnpm fetches it by creating a hard link. 



![Image store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1s4p0rtyt3oclp0p1kga.png)
<em> Figure 3 - Global pnpm store</em>


Because of this approach, pnpm re-uses the same packages if they are already installed for another project. This brings us to the many benefits which pnpm provides. Let’s discuss some of those. 
## Advantages of pnpm
pnpm provides many advantages over npm and yarn. Some of the core features include:
### Disk space efficiency
As shown in the previous section, pnpm uses a content-addressable file system to store the packages and dependencies on the disk. That means the same package will not be duplicated. Even with different versions of the same package, pnpm is intelligent enough to reuse the maximum code. If a package version 1 has 500 files and version 2 has just one more file, then pnpm will not write 501 files for version 2; instead, it will create a hard link to the original 500 files and write just the new file. If you compare it with npm, then version 2 will also be loaded with duplicating the original 500 files. For large monorepo projects, it can make a big difference. Image a scenario where a package is needed by hundreds of other packages that will be killing your disk space unless you use pnpm. 
### Improved speed
The speed of package installation with pnpm is significantly better than npm and yarn. If you look at the below benchmark tests, you can see that pnpm performs better in most cases than npm and yarn. 



![Image comparison](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5t2b9et1nbwo5c8o1zoz.png)
<em> source - https://pnpm.io/benchmarks</em>


 
### Security
pnpm, like yarn, has a special file with the checksum of all the installed packages. This ensures the integrity of all the installed packages before their code is executed. 

In terms of unprivileged access, pnpm also outperforms npm and yarn. In the case of npm and yarn, If package A depends on package B, and B depends on C, then A implicitly gets access to C even though A has not declared C as its dependency. This problem is intensified in a large monorepo setup. Pnpm, on the other hand, uses a different dependency resolution algorithm and different folder structure of  `node_modules` that prevents illegal access to packages. 

Note that pnpm has excellent support for monorepo and offline mode. 
## pnpm CLI
Pnpm has a cool CLI. Here are some of the basic commands:

- `pnpm init`: Create a package.json file 
- `pnpm install`: Download all the packages listed as dependencies in package.json 
- `pnpm add [module_name]@[version]`: Download a particular version of a package and add to the list of dependencies in package.json 
- `pnpm remove [module_name]`: Uninstall and remove a package from the list of dependencies in `package.json` 
- `pnpm list`: Print a tree of locally installed modules 


## Migrating from NPM/Yarn to PNPM
If your projects use npm or yarn, then migrating to pnpm will not be very difficult. Here is a comparison of commands between npm, yarn, and pnpm. 

| npm command                                                               | Yarn command                                            | pnpm equivalent                                         |
| ------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- |
| npm install                                                               | yarn                                                    | [pnpm install](https://pnpm.io/cli/install)             |
| npm install [pkg]                                                         | yarn add [pkg]                                          | [pnpm add [pkg]](https://pnpm.io/cli/add)               |
| npm uninstall [pkg]                                                       | yarn remove [pkg]                                       | [pnpm remove [pkg]](https://pnpm.io/cli/remove)         |
| npm update                                                                | yarn upgrade                                            | [pnpm update](https://pnpm.io/cli/update)               |
| npm list                                                                  | yarn list                                               | [pnpm list](https://pnpm.io/cli/list)                   |
| npm run [scriptName]                                                      | yarn [scriptName]                                       | [pnpm [scriptName]](https://pnpm.io/cli/run)            |
| npx [command]                                                             | [yarn dlx [command]](https://yarnpkg.com/cli/dlx)       | [pnpm dlx [command]](https://pnpm.io/cli/dlx)           |
| [npm exec](https://docs.npmjs.com/cli/v8/commands/npm-exec)               | [yarn exec [commandName]](https://yarnpkg.com/cli/exec) | [pnpm exec [commandName]](https://pnpm.io/cli/exec)     |
| [npm init [initializer]](https://docs.npmjs.com/cli/v8/commands/npm-init) | yarn create [initializer]                               | [pnpm create [initializer]](https://pnpm.io/cli/create) |


## Conclusion
Pnpm is “performant” version of npm, hence the name pnpm. This article showed you the issues with existing package managers like npm and yarn. **pnpm** has brought many improvements, built on top of existing npm features. **pnpm** has adopted all the good things of npm while removing its weaknesses, making **pnpm** the best of both worlds. 

As shown in the above benchmark results, pnpm has overall performed much better than npm and yarn. No wonder giant tech companies like Vue3, Prism, and Microsoft are quickly adopting pnpm. 

<br/>
<div>
<a href="https://discord.gg/refine">
  <img src="https://refine.dev/img/discord_big_blue.png" alt="discord banner" />
</a>
</div>

---
## Stop wasting your time copy/pasting your table code all over your application!


Meet the headless, React-based solution to build sleek **CRUD** applications. With refine, you can be confident that your codebase will always stay clean and boilerplate-free.

Try [refine](https://github.com/pankod/refine) to rapidly build your next **CRUD** project, whether it's an admin panel, dashboard, internal tool or storefront.


<div>
<a href="https://github.com/pankod/refine">
    <img  src="https://refine.dev/img/generic_banner.png" alt="refine blog logo" />
</a>
</div>

<br/>


**refine** is an open-source, React-based framework for building CRUD applications without constraints. It’s headless by design and seamlessly works with **any custom design** or **UI framework** you favor. For convenience, it ships with ready-made integrations for **Ant Design System, Material UI and Mantine UI**.

It can **speed up your development time up to 3X** without compromising freedom on styling, customization and project workflow.

Visit [refine GitHub repository](https://github.com/pankod/refine) for more information, demos, tutorials, and example projects.