Javascript
Development Environment
Pnpm: Package Manager

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

pnpm logo 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: Explanation of how CAS works

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.

pnpm progress log

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 needed
  • reused : number of packages already installed in the CAS repository among resolved
  • downloaded : number of newly downloaded packages among resolved
  • 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.

Installing pnpm packages in parallel

Example parallel installation of pnpm packages (source (opens in a new tab))
.

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.

nested node_modules
▾ 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.

flat node_modules
▾ 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: Installing pnpm with npm

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. Example for pnpm init

  • pnpm install : Install a prebuilt list of dependency packages for the project. Example for pnpm install

  • pnpm add [package_name]: Adds one or more new packages to your project. Example for pnpm add

  • pnpm exec [package_name]: Runs a package you have installed in your project from the command line. Example for pnpm exec

  • pnpm run [script_name] : Runs the npm script specified in the project. pnpm run example pnpm run dev result

5.2. Global package management

  • pnpm dlx [package_name] : Download and run a package temporarily without installing it. phpm dlx example

  • pnpm create [package_name] : Create a new project using the starter kit of a package that supports create. Example for pnpm create

  • pnpm add -g [package_name] : Add a global package. pnpm add -g Example

  • pnpm list -g : List all installed global packages. pnpm list -g Example

For more commands, type pnpm.

pnpm command list

copyright for Javascript pnpm install

© 2023 All rights reserved.