Install pnpm: the next generation JS package manager, 2x faster than npm and yarn
Introducing pnpm, the younger sibling of the JS package manager trio. I'll try to explain how pnpm works faster than npm and yarn, and organize how to install and use it.
1. Introducing pnpm
The official pnpm home page: https://pnpm.io/ (opens in a new tab)
pnpm is a next-generation JS package manager designed to overcome the performance limitations of traditional JS package managers. The name pnpm stands for Performant npm, and you can tell from the name that it's designed for efficient performance.
Using it is almost identical to using other package managers.
It works on the basis of a package.json
file and can replace almost all the features of npm and yarn.
The command line ming is built to be more like yarn.
2. Three Advantages of pnpm
There are three main advantages to using pnpm.
It saves disk space, makes dependency installation faster, and organizes the node_modules
directory structure more efficiently.
Let's look at them one at a time.
2.1. Less disk usage
The reason pnpm can do the same thing and use less disk space is because it uses a central repository called content-addressable storage (CAS). When you install a package with pnpm, all packages are stored in this repository. And every project that uses pnpm gets the packages it needs from that repository.
For example, if I created three React projects with npm, the React package would be installed in each project's node_modules
directory.
This means I have 3 of the same packages installed on my machine.
However, if I use pnpm, only one react package is installed in the CAS repository, and all three projects share that package.
Explanation of how CAS works with pnpm:
If there are different versions of a package that you need, the CAS repository handles this efficiently. It only downloads and stores the files that have changed for each version. This is similar to the dependency management algorithm in Docker.
In JS/TS development, it's easy to find duplicate packages in any project, or packages that depend on multiple packages at the same time. In these cases, the amount of disk space saved by pnpm can be significant.
The above is the progress log output when installing some packages with pnpm. Each number in the last line means
resolved
: total number of packages neededreused
: number of packages already installed in the CAS repository amongresolved
downloaded
: number of newly downloaded packages amongresolved
added
: Number of packages added to the project as a result.
In the above case, since there are no new packages to download, there is no disk or network usage, which should speed up the installation time. You can even add packages to the project offline if they are installed in a CAS repository.
2.2. Faster Dependency Package Installations
The first reason pnpm can do dependency installations faster is because of the CAS repository mentioned above. First of all, it doesn't reinstall packages that are already in the repository, and there are significantly fewer files to download when a version is upgraded, so it's no wonder it's faster.
Second, pnpm supports parallel installation of packages.
JS package managers follow a three-step process for installing dependencies: [identify the dependencies you need -> download -> compile the package ]. In the case of npm, all packages must complete one step before moving on to the next. Since pnpm assumes that packages don't interfere with each other, each package can do step 3 separately.
In the graph below, the horizontal axis is time and the vertical axis is each package. Even if all packages don't finish the previous step, the one that finishes first will proceed to the next step, making the whole installation process faster.
2.3. Tighter and more efficient node_modules directory
The first of the three dependency installation steps mentioned above, identifying the required dependencies, is called dependency resolution. In this step, the package manager keeps track of the packages this project uses and the packages they depend on, and plans to install them all.
Up until npm version 2, we used to install all packages at this stage, which caused two problems.
First, if both package A
and package B
had package C
as a dependency, they were installed twice, even though they were duplicates.
This is unnecessary duplication.
Second, each package's node_modules
directory was installed with its tail between its legs.
This is called nested node_modules, like the directory structure below.
▾ node_modules
▾ package A
▾ node_modules
▸ package C
▾ package B
▾ node_modules
▾ package C
▸ node_modules
In npm 3+ and yarn, we use the flat node_modules structure to solve this problem.
This is a way to install all packages under node_modules
in a project, regardless of their dependency depth.
▾ node_modules
▾ .bin
▾ accepts
▾ array-flatten
...
▾ etag
▾ express
This flat structure prevents duplicate installs, but it also introduces another problem.
This is that any package I install as a dependency can be used in this project, even if it's not explicitly installed via package.json
.
For example, I'm using version 1 of package S
, which I installed as a dependency of package A
without putting it in package.json
,
What happens if we need to upgrade to version 2 of package S
?
Since we don't keep track of package S
, it would be impossible to upgrade automatically, resulting in a runtime error.
PNPM prevents this.
The package files in node_modules
created with pnpm are all symlinks or hard links to the actual files in the CAS repository, so they can be freely restructured and optimized.
This allows us to solve the problem of duplicate packages without having to use a flat structure, and to restrict access to only those packages that we have explicitly installed.
3. Intermediate organization
As you can see, pnpm is more than twice as efficient as traditional package managers simply by eliminating as much duplication as possible through the use of CAS repositories. We've also gained a lot of stability in the process.
Now let's take a quick look at how to install and use pnpm.
4. How to install
It is recommended that you install pnpm globally using npm. It can be installed with a simple command. Of course it also works on Windows.
npm install -g pnpm
Result of execution:
It is also possible to install using Corepack for Node.js, but this is still experimental, so I won't describe it.
5. How to use it
The usage is almost the same as for npm and yarn.
5.1. Managing packages in the project
-
pnpm init
: Start a new project which will be managed by pnpm. -
pnpm install
: Install a prebuilt list of dependency packages for the project. -
pnpm add [package_name]
: Adds one or more new packages to your project. -
pnpm exec [package_name]
: Runs a package you have installed in your project from the command line. -
pnpm run [script_name]
: Runs the npm script specified in the project.
5.2. Global package management
-
pnpm dlx [package_name]
: Download and run a package temporarily without installing it. -
pnpm create [package_name]
: Create a new project using the starter kit of a package that supports create. -
pnpm add -g [package_name]
: Add a global package. -
pnpm list -g
: List all installed global packages.
For more commands, type pnpm
.
