toolfree

npm → pnpm

The npm command you know beside its pnpm equivalent, for every common task — plus what changes when node_modules stops being flat.

Runs in your browser

Tasknpmpnpm
Install everything in the lockfile
Install for CI, failing if the lockfile would change
Add a dependency
Add a dev dependency
Add without a version range
Install globally
Remove a dependency
Update within the declared ranges
List packages behind their latest
Run a script from package.json
Run a package binary without installing it
Start a new package
Explain why a package is installed
Check dependencies for advisories
Add a dependency to one workspace

The short version

npmpnpm
npm installpnpm install — or pnpm i
npm install <pkg>pnpm add <pkg>
npm install -D <pkg>pnpm add -D <pkg>
npm uninstall <pkg>pnpm remove <pkg>
npm run buildpnpm build
npx <pkg>pnpm dlx <pkg>
npm install <pkg> -w <name>pnpm --filter <name> add <pkg>

pnpm’s command surface is deliberately close to npm’s, so the translation is almost mechanical. The full table is above, with your package name filled in.

What actually changes

The commands are the easy part. The install layout is the reason to switch and the reason something breaks.

node_modules is not flat. npm and Yarn 1 hoist every transitive dependency to the top level, which means code can require('some-package') that it never declared, and it works. pnpm puts only your declared dependencies at the top and symlinks the rest from a content-addressed store.

That is a real bug-finder, and it will find bugs in packages you did not write. A package that relied on hoisting fails under pnpm with Cannot find module. The fix is usually public-hoist-pattern in .npmrc, and sometimes filing an issue upstream.

Disk usage collapses. Every version of every package is stored once per machine and hard-linked into projects. Ten projects on the same React version cost one copy.

pnpm dlx is not npx with a different name. npx will happily run a binary already present in the local node_modules; pnpm dlx always fetches into a temporary store and runs that. Use pnpm exec for the local binary.

Migrating a project

  1. Delete package-lock.json and node_modules.
  2. Run pnpm install.
  3. Run the build and the test suite. This is where the hoisting assumptions surface, not at install time.
  4. Commit pnpm-lock.yaml, and only pnpm-lock.yaml.

For a monorepo, add pnpm-workspace.yaml. pnpm does not read the workspaces field in package.json — this is the single most common thing to get stuck on, because the install succeeds and simply does not link anything.

npm to Yarn, or the full four-way table including Bun.