pnpm / yarn / bun
Choosing between npm, pnpm, and yarn: install speed, lockfiles, monorepo features, and the migration story.
Node — npm vs pnpm vs yarn
EXAMPLE
# ===== TL;DR =====
# npm ships with Node; battle-tested; lockfile package-lock.json; ok speed
# pnpm fastest installs; content-addressable store; strict node_modules; great for monorepos
# yarn Berry (yarn 3+); Plug-n-Play option; workspaces are mature; lockfile yarn.lock
# In 2026, pnpm is the smart default for most new projects.
# ===== Install =====
# pnpm:
curl -fsSL https://get.pnpm.io/install.sh | sh
# or: corepack enable && corepack prepare pnpm@latest --activate
pnpm --version
# yarn:
corepack enable && corepack prepare yarn@stable --activate
yarn --version
# ===== Daily commands =====
# Add a dep:
npm install lodash
pnpm add lodash
yarn add lodash
# Dev dep:
npm i -D vitest
pnpm add -D vitest
yarn add -D vitest
# Remove:
npm uninstall lodash
pnpm remove lodash
yarn remove lodash
# Reinstall from lockfile (CI):
npm ci
pnpm install --frozen-lockfile
yarn install --immutable
# Run a script:
npm run build
pnpm build # pnpm allows short form
yarn build
# ===== Why pnpm =====
# - Hard links from a global store -> disk space scales sub-linearly
# - Strict tree: package can only import deps it declares (no phantom deps)
# - Fast: usually 2-3x faster than npm install in cold + warm cache
# - Workspaces native + simple
# ===== Why yarn =====
# - Berry's Plug-n-Play removes node_modules entirely (smaller, faster, stricter)
# - Mature workspaces + constraints + protocols
# - Less common surprises in monorepos
# - Choose 'node-modules' linker if PnP breaks tools
# ===== Why npm still =====
# - Default; everyone has it
# - Less surprise; smaller team coming up to speed
# - Recent versions are reasonably fast
# - Workspaces work (basic features)
# ===== Monorepo features (workspaces) =====
# package.json (root):
{
"private": true,
"workspaces": ["packages/*"] // npm + yarn
}
# pnpm uses pnpm-workspace.yaml:
packages:
- 'packages/*'
- 'apps/*'
# ===== Migration =====
# npm -> pnpm:
pnpm import # converts package-lock.json -> pnpm-lock.yaml
# git rm package-lock.json
# add 'pnpm-lock.yaml' to repo
# yarn -> pnpm: rerun installs; review hoisting warnings.
# ===== CI tips =====
# Cache the package manager store:
# pnpm: ~/.local/share/pnpm/store
# yarn: ~/.yarn/berry
# npm: ~/.npm
# GitHub Actions: setup-node with cache: 'pnpm' / 'yarn' / 'npm' handles this.
# ===== Patterns to internalise =====
# - Pick ONE per repo; commit the lockfile
# - Use corepack to pin the package manager version
# - In CI: --frozen-lockfile / npm ci / --immutable to refuse drift
# - workspaces for monorepos; do not roll your own symlinks
# ===== Pitfalls =====
# - Mixing managers in one repo -> two lockfiles, broken installs
# - Phantom deps in npm/yarn -> code imports a dep it does not declare
# - PnP breaking tools that scan node_modules
# - Forgetting to pin via corepack -> different machines, different versions
Why it matters
pnpm is the smart default in 2026: fast installs, strict tree, easy monorepos. yarn Berry shines on PnP-friendly stacks. npm remains the safe baseline. Pin the manager via corepack, commit the lockfile, and use frozen / immutable installs in CI.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# pnpm — fast, disk-efficient pnpm add zod # yarn (v4) — also great yarn add zod # bun — both runtime and pm bun add zodTry it Yourself »
Discussion
Loading…