NPM vs PNPM cheatsheet
Comparison of the most useful npm vs pnpm scripts/commands, side-by-side, including workspace-related ones. Useful for daily use, monorepos, and publishing workflows.
⚙️ Setup & Installation
| Task | npm | pnpm |
|---|---|---|
| Init a project | npm init | pnpm init |
| Init with defaults | npm init -y | pnpm init -y |
| Install deps | npm install | pnpm install |
| Install specific pkg | npm install lodash | pnpm add lodash |
| Install dev dep | npm install -D typescript | pnpm add -D typescript |
| Install globally | npm install -g nodemon | pnpm add -g nodemon |
| Remove package | npm uninstall lodash | pnpm remove lodash |
| Update packages | npm update | pnpm update |
| Install exact version | npm install react@18.2.0 | pnpm add react@18.2.0 |
📦 Lockfiles & Node Modules
| Task | npm | pnpm |
|---|---|---|
| Lockfile | package-lock.json | pnpm-lock.yaml |
| Node modules | flat structure | symlinked, content-addressed |
| Reinstall from lockfile | npm ci | pnpm install --frozen-lockfile |
| Clear cache | npm cache clean --force | pnpm store prune |
| Prune unused deps | npm prune | pnpm prune |
🧪 Scripts & Running
| Task | npm | pnpm |
|---|---|---|
| Run script | npm run dev | pnpm dev |
| Run script (with args) | npm run build -- --watch | pnpm build --watch |
| Run bin from deps | npx eslint . | pnpm exec eslint . |
| Run multiple scripts | npm run dev1 & npm run dev2 | pnpm -r run dev |
| Open interactive shell | (no equivalent) | pnpm dlx |
🧱 Workspaces (Monorepos)
| Task | npm | pnpm |
|---|---|---|
| Enable workspaces | Add "workspaces" to package.json | Same, plus pnpm-workspace.yaml |
| Run script in all packages | npm run build --ws (v8+) | pnpm -r run build |
| Run script in one package | (cd to pkg dir) | pnpm --filter pkg-name run build |
| Install in one workspace package | (cd to pkg dir) | pnpm add lodash --filter pkg-name |
| Recursive install | npm install | pnpm install |
| List workspace packages | npm ls --workspaces | pnpm list -r |
📦 Publishing
| Task | npm | pnpm |
|---|---|---|
| Login to registry | npm login | pnpm login |
| Publish a package | npm publish | pnpm publish |
| Publish with access | npm publish --access public | pnpm publish --access public |
| Tag a release | npm version patch | pnpm version patch |
| Publish in monorepo | (manual or Lerna) | pnpm publish -r |
Bonus
| Task | npm | pnpm |
|---|---|---|
| Show outdated packages | npm outdated | pnpm outdated |
| Audit for vulnerabilities | npm audit | pnpm audit |
| Link local package | npm link | pnpm link |
| List global packages | npm list -g --depth 0 | pnpm list -g --depth 0 |
| Add package in another workspace | (cd into workspace manually) | pnpm add lodash --filter=other-pkg |
pnpm exec
"Use package already installed in the project."
- Runs a binary from your dependencies or globally installed (local
node_modules/.bin) - It does not install anything new.
pnpm exec eslint src/pnpm dlx
"Temporarily download & execute a binary."
- Temporarily installs a package, runs its CLI, then discards it.
- Useful for one-off CLIs or generators you don’t want to install.
pnpm dlx create-next-app@latest my-app