Learn

pnpm in practice

The package manager that saves gigabytes via a global store and hardlinks.

pnpm (Performant npm) is a drop-in replacement for npm built on two strong ideas: a global store on disk that holds only one copy of each package, and strict resolution that prevents phantom dependencies.

Why pnpm saves so much space

When you run npm install react, npm copies the files into your-project/node_modules/react/. If you have ten projects using React, you have ten identical copies on disk.

pnpm works differently:

  1. It downloads React once into a global store (~/.local/share/pnpm/store on Linux/macOS, %LOCALAPPDATA%\pnpm\store on Windows).
  2. In each project, node_modules/react/ is a hardlink pointing to the store files. One physical file, ten projects accessing it.

Concretely: on a machine with ten React projects, npm uses ~400 MB per project. pnpm uses ~40 MB (the shared store) regardless of how many projects there are.

Installing pnpm

Via npm (once):

shell
npm install -g pnpm

Via corepack (included in Node since v16):

shell
corepack enable
shell
corepack prepare pnpm@latest --activate

Verify:

shell
pnpm --version

Common commands

Install all dependencies for an existing project:

shell
pnpm install

Add a package:

shell
pnpm add react

Add a devDependency:

shell
pnpm add -D typescript

Run a script defined in package.json:

shell
pnpm run dev

Shorthand (without run) for common scripts:

shell
pnpm dev
shell
pnpm build
shell
pnpm test

Run a one-off command without installing globally:

shell
pnpm dlx create-next-app my-app

Update all dependencies:

shell
pnpm update

Remove a package:

shell
pnpm remove lodash

Strict resolution: no more phantom dependencies

pnpm creates a non-flattened node_modules/ structure. Each package can only see its own declared dependencies. Your code cannot access lodash unless you have explicitly added lodash to your package.json.

This may seem restrictive, but it is a safety net: your build is reproducible and does not depend on the transitive dependencies of your dependencies.

pnpm and monorepos

pnpm has the best monorepo support among the three package managers. A pnpm-workspace.yaml file at the root is all you need to declare multiple packages:

yaml
packages:
  - "packages/*"
  - "apps/*"

Packages in the workspace can reference each other with workspace:* as the version:

json
{
  "dependencies": {
    "@my-project/shared": "workspace:*"
  }
}
Official pnpm documentation pnpm Workspaces

Check off steps to unlock what comes next

Back to course