npm vs pnpm vs Yarn vs Bun: Which Package Manager Should You Use?
Four JavaScript package managers install the same packages in different ways. How npm, pnpm, Yarn and Bun differ on speed, disk space, lockfiles and safety, which lockfile belongs to which, and why mixing them breaks things.
Every JavaScript project installs packages — the libraries listed in package.json. There are four popular tools for doing it: npm, pnpm, Yarn and Bun. They all read the same package.json and download from the same registry. The differences are in speed, disk use, strictness and safety defaults.
(New to this? Start with what are npm and package.json?)
The quick answer
- Starting out, or following a tutorial: npm. It comes with Node.js and everything documents it.
- You want faster installs and less disk space, with stricter rules: pnpm.
- Your project already uses Yarn: keep using Yarn.
- Your project runs on the Bun runtime, or you want the fastest installs: Bun.
- Most important rule: use whichever one the project already uses. Look at the lockfile.
How to tell which one a project uses
Each tool writes its own lockfile — the exact record of every package version installed:
| Lockfile | Package manager |
|---|---|
package-lock.json |
npm |
pnpm-lock.yaml |
pnpm |
yarn.lock |
Yarn |
bun.lock (older: bun.lockb) |
Bun |
Many projects also declare it in package.json:
"packageManager": "pnpm@10.0.0"
The four, briefly
npm
Comes bundled with Node.js, so it's always there. The default in nearly every tutorial and AI-generated README. Perfectly good for most projects. Commands: npm install, npm run dev, npm ci for clean installs in CI.
pnpm
Stores each package version once on your disk and links it into each project, instead of copying it every time. Ten projects using the same React version share one copy. Results: much less disk space and fast installs.
pnpm is also strict: your code can only import packages you've actually listed in package.json. With npm, code sometimes works by accident because a package your dependency installed happens to be lying around in node_modules. pnpm catches that. And since pnpm 10, dependencies' install scripts don't run by default unless you allow them — a meaningful supply-chain safety improvement.
Yarn
Created by Facebook in 2016 when npm was slow and unreliable; it introduced lockfiles to the mainstream. npm has since caught up on most of what made Yarn special. Modern Yarn (version 2 and later, "Berry") is quite different from Yarn 1 and offers an optional "Plug'n'Play" mode without a node_modules folder. Large existing projects and some monorepos use it.
Bun
Bun is a whole JavaScript runtime (an alternative to Node.js) that also includes a package manager. bun install is extremely fast and works in ordinary Node.js projects too. Like pnpm, it doesn't run dependencies' install scripts unless you trust them. See Node vs Bun vs Deno for the runtime side.
Compared
| npm | pnpm | Yarn | Bun | |
|---|---|---|---|---|
| Comes with Node.js | Yes | No | No | No |
| Install speed | Good | Fast | Fast | Fastest |
| Disk use across projects | High | Low | Varies | Low |
| Strict about undeclared imports | No | Yes | In PnP mode | No |
| Runs dependency install scripts by default | Yes | No | Yes | No |
Don't mix them
The classic beginner mess: a project has both package-lock.json and pnpm-lock.yaml, because someone ran npm install in a pnpm project (or an AI tool did). Now two lockfiles disagree about versions, and "works on my machine" bugs follow.
Fix it:
- Decide which manager the project uses.
- Delete the other lockfiles and
node_modules. - Run a fresh install with the chosen tool.
- Add a line to your
CLAUDE.mdor README: "This project uses pnpm. Never run npm install." AI tools follow it. (How to write a CLAUDE.md)
Commands cheat sheet
| Task | npm | pnpm | Yarn | Bun |
|---|---|---|---|---|
| Install everything | npm install |
pnpm install |
yarn |
bun install |
| Add a package | npm install zod |
pnpm add zod |
yarn add zod |
bun add zod |
| Add a dev package | npm install -D vitest |
pnpm add -D vitest |
yarn add -D vitest |
bun add -d vitest |
| Run a script | npm run dev |
pnpm dev |
yarn dev |
bun run dev |
| Clean install (CI) | npm ci |
pnpm install --frozen-lockfile |
yarn install --immutable |
bun install --frozen-lockfile |
The summary
- All four install the same packages; they differ in speed, disk use, strictness and safety defaults.
- npm is the default; pnpm is fast, strict and safer by default; Bun is fastest; Yarn suits projects already on it.
- The lockfile tells you which one a project uses. Never mix them.
EasySpawn servers have npm, pnpm, Yarn and Bun ready, and keep your installed dependencies on persistent storage — so installs don't start from zero every session. See how it works or join the waitlist.
Related: Semantic Versioning Explained · How to Update Your App's Dependencies Safely · npm audit Explained · npm ERESOLVE Errors
Keep reading
What Is WSL? Running Linux on Windows, Explained
WSL lets you run a real Linux system inside Windows without dual-booting or a separate virtual machine to manage. What it is, why web developers use it, how to install it, where your files live, and the performance and networking gotchas.
What Is an IDE? Code Editors vs IDEs Explained
An IDE (integrated development environment) puts everything you need to write software in one app: editor, file browser, terminal, debugger, git and more. How it differs from a plain code editor, the popular options, cloud IDEs, and where AI fits in.