TypeScript

Why You Might Want to Switch to pnpm from npm

I switched a monorepo with 12 packages from npm to pnpm. Install time dropped from 4 minutes to 45 seconds. Disk usage dropped by 60%.

7 Sept 2024

Why You Might Want to Switch to pnpm from npm

I switched a monorepo with 12 packages from npm to pnpm. Install time dropped from 4 minutes to 45 seconds. Disk usage dropped by 60%.

Here's why.

It doesn't duplicate packages

npm copies every dependency into each project's node_modules. If ten projects use the same version of lodash, you get ten copies.

pnpm stores packages in a global content-addressable store and creates hard links. One copy on disk, shared everywhere. On a machine with many projects, this saves gigabytes.

Faster installs

pnpm installs packages in parallel and uses its global cache aggressively. Once a package is downloaded, it's available to every project on the machine without re-downloading.

In practice, this means CI pipelines and fresh clones are significantly faster.

Strict dependency resolution

npm has a problem called "phantom dependencies." Your code can accidentally import a package that's installed as a transitive dependency — one you never listed in your package.json. It works until someone upgrades the parent package and the transitive dep disappears.

pnpm prevents this. It only makes your declared dependencies accessible. If you didn't list it, you can't import it. This catches real bugs.

Built for monorepos

pnpm's workspace feature handles multi-package repos natively. Shared dependencies are hoisted correctly. Versions stay consistent. No need for separate tools like Lerna for basic workspace management.

Better lockfile

pnpm-lock.yaml is more deterministic than package-lock.json. It produces more consistent and reproducible builds across different machines and CI environments.

The trade-off

pnpm is faster, more disk-efficient, and stricter about dependency correctness. For monorepos, it's the clear winner.

The cost: some packages assume npm's flat node_modules structure and break under pnpm's strict isolation. You'll occasionally need to add entries to .pnpmfile.cjs or use shamefully-hoist to fix compatibility issues. And your team needs to learn a slightly different CLI — pnpm add instead of npm install, pnpm dlx instead of npx.

For most projects, those are small prices for big gains.

Keep reading