Blog
4 min read

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:

  1. Decide which manager the project uses.
  2. Delete the other lockfiles and node_modules.
  3. Run a fresh install with the chosen tool.
  4. Add a line to your CLAUDE.md or 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