Why you should prefer using pnpm ?

Necati Özmen - Oct 13 '22 - - Dev Community

Author: Muhammad Khabbab

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?

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
Figure 1 - Example project dependencies

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.

Image structure
Figure 2 - project structure with pnpm

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
Figure 3 - Global pnpm store

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
source - https://pnpm.io/benchmarks

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
npm install [pkg] yarn add [pkg] pnpm add [pkg]
npm uninstall [pkg] yarn remove [pkg] pnpm remove [pkg]
npm update yarn upgrade pnpm update
npm list yarn list pnpm list
npm run [scriptName] yarn [scriptName] pnpm [scriptName]
npx [command] yarn dlx [command] pnpm dlx [command]
npm exec yarn exec [commandName] pnpm exec [commandName]
npm init [initializer] yarn create [initializer] pnpm create [initializer]

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.


discord banner


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 to rapidly build your next CRUD project, whether it's an admin panel, dashboard, internal tool or storefront.


refine blog logo

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 for more information, demos, tutorials, and example projects.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .