Skip to main content

Best JavaScript Package Managers in 2026: npm vs pnpm vs Yarn

·PkgPulse Team

TL;DR

pnpm for monorepos and disk efficiency; npm for simplicity; Yarn Berry for Plug'n'Play. pnpm (~12M weekly downloads) uses a content-addressable store — install each package version once on your machine, hard-link everywhere. npm (~100M+ is built into Node.js, used everywhere. Yarn Berry (~6M downloads) with PnP eliminates node_modules entirely but has ecosystem compatibility issues. For new projects in 2026, pnpm is the technical winner; npm is the safe default.

Key Takeaways

  • npm: ~100M+ downloads — built into Node.js, largest ecosystem, default for most
  • pnpm: ~12M downloads — 2x faster installs, 70% less disk space, strictest resolution
  • Yarn Berry: ~6M downloads — PnP mode eliminates node_modules; workspace support
  • Bun: ~2M downloads — 3-5x faster than npm, all-in-one runtime+bundler+pm
  • pnpm workspaces — best-in-class monorepo support with workspace protocol

npm (The Standard)

# npm — built into Node.js, no install needed
npm install react react-dom
npm install -D typescript @types/react

# Workspaces
npm install --workspace=apps/web react
npm run build --workspace=apps/web

# Common flags
npm install --legacy-peer-deps   # Fix peer dep conflicts
npm ci                           # Clean install from lockfile (CI)
npm audit                        # Security audit
npm outdated                     # List outdated packages
npm update                       # Update within semver ranges
// package.json — npm workspaces
{
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "build": "npm run build --workspaces --if-present",
    "test": "npm test --workspaces --if-present"
  }
}
# npm lockfile — package-lock.json
# Always commit this file! It ensures reproducible installs.
# If you see conflicts, resolve by running npm install locally.

# npm 7+ — automatic peer deps install
# npm 8+ — workspaces --if-present flag
# npm 9+ -- better provenance and audit features
# npm 10+ -- improved caching, workspace improvements

# Install pnpm
npm install -g pnpm
# or: curl -fsSL https://get.pnpm.io/install.sh | sh -

# pnpm commands (same API as npm)
pnpm install
pnpm add react react-dom
pnpm add -D typescript
pnpm remove lodash

# The magic: content-addressable store
# ~/.pnpm-store — packages stored ONCE, hard-linked
# node_modules/.pnpm — virtual store with flat deps
# pnpm-workspace.yaml — monorepo config
packages:
  - 'apps/*'
  - 'packages/*'
  - '!**/test/**'
# pnpm workspace commands
pnpm --filter web install          # Install deps for web only
pnpm --filter web build            # Build web package
pnpm --filter '...web' build       # Build web and its deps
pnpm --filter './packages/**' test # Test all packages
pnpm -r build                      # Recursive: build all

# pnpm workspace protocol
# In apps/web/package.json:
# "dependencies": { "@myrepo/ui": "workspace:*" }
# This links to the local package — no version pinning needed
# pnpm performance vs npm
# Fresh install (200 packages):
# npm:  45s
# pnpm: 22s  (2x faster, ~70% less disk)
# yarn: 30s

# Cached install:
# npm:  15s
# pnpm: 5s   (3x faster)
# yarn: 8s
# .npmrc — pnpm strict mode (prevents phantom dependencies)
shamefully-hoist=false        # Don't hoist transitive deps to root
strict-peer-dependencies=true # Fail on peer dep conflicts

Yarn Berry (PnP)

# Yarn Berry — enable in project
yarn set version stable        # Switch to Yarn Berry
# or: yarn set version berry

# .yarnrc.yml — created automatically
# .yarnrc.yml — Yarn Berry config
nodeLinker: pnp           # Plug'n'Play (no node_modules)
# nodeLinker: node-modules # Traditional (if PnP compatibility issues)

yarnPath: .yarn/releases/yarn-4.x.y.cjs
# Yarn Berry PnP — key difference
# PnP: No node_modules! Uses .pnp.cjs for module resolution
# Benefit: 70% faster cold installs, zero phantom deps
# Problem: ~15% of packages are PnP-incompatible (check compatibility)

# Check if a package works with PnP:
yarn dlx @yarnpkg/doctor

# Common PnP issues:
# 1. require('some-package') in scripts (use 'import' instead)
# 2. Packages using __dirname in non-standard ways
# 3. Some native addons

# If PnP breaks too many things:
# nodeLinker: node-modules  # Fall back to traditional
# Yarn Berry workspaces
yarn workspaces list
yarn workspace web add react
yarn workspaces foreach run build
yarn workspace @myrepo/ui test

Bun (Speed Demon)

# Bun — all-in-one: runtime + bundler + package manager
curl -fsSL https://bun.sh/install | bash

# bun install — 3-5x faster than npm
bun install
bun add react react-dom
bun remove lodash

# Bun uses npm registry — fully compatible
# bun.lockb — binary lockfile (fast to read, not human-readable)

# Run scripts with bun runtime
bun run start          # Much faster than: node server.js
bun run dev            # ts files work natively, no transpile step
bun test               # Built-in test runner (Jest-compatible)

Installation Speed Benchmark

Package ManagerCold InstallWarm InstallDisk Space
Bun~8s~1sMedium
pnpm~22s~5sMinimal (shared store)
Yarn Berry (PnP)~15s~3sMinimal
Yarn Berry (nm)~28s~8sMedium
npm~45s~15sLarge

Benchmarks for create-react-app style project (~200 deps). Your numbers will vary.


When to Choose

ScenarioPick
New project, no specific needspnpm
Monorepo with many packagespnpm (workspace: protocol)
CI/CD speed is criticalpnpm or Bun
Disk space is limitedpnpm (shared store)
Zero-compromise compatibilitynpm
Bun-native projectBun
Already using Yarn, migratingYarn Berry (with node-modules linker)
Zero node_modules (advanced)Yarn Berry PnP
Corporate environment, no choicesnpm

Compare package manager stats on PkgPulse.

See the live comparison

View npm vs. pnpm on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.