- Replace .eslintrc.cjs with eslint.config.mjs (ESLint 9 flat config)
using direct eslint-plugin-solid + @typescript-eslint/parser approach
- Add @typescript-eslint/parser to root devDependencies
- Add main/module/types top-level fields to packages/core/package.json
- Add resolve.conditions to packages/core/vite.config.ts
- Create packages/core/tsconfig.test.json for test type-checking
- Remove empty paths:{} from packages/core/tsconfig.json
256 lines
8.6 KiB
Markdown
256 lines
8.6 KiB
Markdown
[Skip to main content](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026#main-content)
|
|
|
|
## [TL;DR](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#tldr)
|
|
|
|
**pnpm is the 2026 default for serious JavaScript projects — content-addressable store, strict dependency isolation, and the best monorepo support.** Bun is 5-10x faster than pnpm on installs but still has edge cases with niche packages. npm is the default that works everywhere but is the slowest. For new projects: pnpm (or Bun if you're already in the Bun ecosystem). For CI speed: Bun's install is often faster than even pnpm's cached install.
|
|
|
|
## [Key Takeaways](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#key-takeaways)
|
|
|
|
- **Bun install**: 5-10x faster than pnpm, 15-25x faster than npm (measured on real projects)
|
|
- **pnpm**: Strictest isolation (prevents phantom dependencies), best workspace support, most compatible
|
|
- **npm**: Default, slowest, but universally compatible, `node_modules` phantom deps allowed
|
|
- **Disk usage**: pnpm uses ~50% less disk space vs npm (content-addressable store deduplication)
|
|
- **Monorepos**: pnpm workspaces > Bun workspaces > npm workspaces (feature parity gap)
|
|
- **2026 recommendation**: pnpm for serious projects; Bun install if on Bun runtime already
|
|
|
|
* * *
|
|
|
|
## [Downloads / Usage](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#downloads--usage)
|
|
|
|
| Package Manager | Weekly Downloads | Trend |
|
|
| --- | --- | --- |
|
|
| `npm` | Default (Node.js) | → Stable |
|
|
| `pnpm` | ~7M downloads/week | ↑ Growing |
|
|
| `bun` | ~1.5M downloads/week | ↑ Fast growing |
|
|
|
|
* * *
|
|
|
|
## [Install Speed Benchmarks](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#install-speed-benchmarks)
|
|
|
|
```
|
|
Benchmark: Next.js 15 project (1,847 packages)
|
|
Environment: M3 MacBook Pro, SSD, cold/warm cache
|
|
|
|
COLD INSTALL (no cache, no lockfile):
|
|
npm: 82s
|
|
pnpm: 31s (2.6x faster than npm)
|
|
Bun: 8s (10x faster than npm)
|
|
|
|
CACHED INSTALL (lockfile present, store exists):
|
|
npm: 45s (reads node_modules hash)
|
|
pnpm: 4s (hardlinks from content store)
|
|
Bun: 0.8s (binary cache, near-instant)
|
|
|
|
CI INSTALL (lockfile present, fresh machine):
|
|
npm: 62s
|
|
pnpm: 18s (3.4x faster)
|
|
Bun: 6s (10x faster)
|
|
```
|
|
|
|
* * *
|
|
|
|
## [pnpm: The Recommended Default](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#pnpm-the-recommended-default)
|
|
|
|
```bash
|
|
# Install pnpm:
|
|
npm install -g pnpm
|
|
# Or via Corepack (Node.js built-in):
|
|
corepack enable pnpm
|
|
|
|
# Common commands:
|
|
pnpm install # Install from lockfile
|
|
pnpm add react # Add dependency
|
|
pnpm add -D typescript # Add dev dependency
|
|
pnpm remove lodash # Remove package
|
|
pnpm update --interactive # Interactive update UI
|
|
pnpm why lodash # Why is this installed?
|
|
pnpm ls # List installed packages
|
|
```
|
|
|
|
```yaml
|
|
# .npmrc — pnpm configuration:
|
|
# Enforce strict peer dependencies:
|
|
strict-peer-dependencies=true
|
|
|
|
# Hoist patterns (allow certain phantom deps for compat):
|
|
public-hoist-pattern[]=*eslint*
|
|
public-hoist-pattern[]=*prettier*
|
|
|
|
# Save exact versions:
|
|
save-exact=true
|
|
|
|
# Node linker (for compatibility with some tools):
|
|
# node-linker=hoisted # Falls back to npm-style if needed
|
|
```
|
|
|
|
```json
|
|
// pnpm-workspace.yaml — monorepo config:
|
|
{
|
|
"packages": [\
|
|
"apps/*",\
|
|
"packages/*",\
|
|
"tools/*"\
|
|
]
|
|
}
|
|
```
|
|
|
|
```bash
|
|
# pnpm workspace commands:
|
|
pnpm --filter web add react-query # Add to specific package
|
|
pnpm --filter "!web" install # Install all except web
|
|
pnpm -r run build # Run build in all packages
|
|
pnpm --filter web... run build # Build web + its dependencies
|
|
pnpm --filter ...web run build # Build packages that depend on web
|
|
```
|
|
|
|
### [Why pnpm Over npm](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#why-pnpm-over-npm)
|
|
|
|
```
|
|
pnpm advantages:
|
|
→ No phantom dependencies (package.json must declare everything)
|
|
→ 50% less disk usage (hardlinks, not copies)
|
|
→ 3-5x faster installs than npm
|
|
→ Best workspace support (filtering, recursive)
|
|
→ Isolated node_modules (each package sees only its deps)
|
|
|
|
pnpm limitations:
|
|
→ Occasional compatibility issues with poorly-written packages
|
|
→ Slightly steeper learning curve for teams migrating from npm
|
|
→ Some tools (older ones) expect hoisted node_modules
|
|
```
|
|
|
|
* * *
|
|
|
|
## [Bun: When Speed Is Everything](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#bun-when-speed-is-everything)
|
|
|
|
```bash
|
|
# Install Bun:
|
|
curl -fsSL https://bun.sh/install | bash
|
|
|
|
# Bun install commands (compatible with npm syntax):
|
|
bun install # Install from lockfile
|
|
bun add react # Add dependency
|
|
bun add -d typescript # Add dev dependency (note: -d not -D)
|
|
bun remove lodash # Remove
|
|
bun update # Update all packages
|
|
```
|
|
|
|
```bash
|
|
# bun.lock — Bun's lockfile format:
|
|
# Binary lockfile (bun.lockb) in older versions
|
|
# Text lockfile (bun.lock) in Bun 1.1+
|
|
# Commit bun.lock to version control
|
|
```
|
|
|
|
```toml
|
|
# bunfig.toml — Bun configuration:
|
|
[install]
|
|
# Use a private registry:
|
|
registry = "https://registry.npmjs.org"
|
|
exact = true # Pin exact versions
|
|
|
|
[install.scopes]
|
|
# Scoped registry:
|
|
"@mycompany" = { token = "$NPM_TOKEN", url = "https://npm.mycompany.com" }
|
|
```
|
|
|
|
```bash
|
|
# Bun workspaces:
|
|
# package.json at root:
|
|
# {
|
|
# "workspaces": ["apps/*", "packages/*"]
|
|
# }
|
|
|
|
bun install # Installs all workspaces
|
|
bun add react --workspace apps/web # Add to specific workspace
|
|
bun run --filter '*' build # Run build in all workspaces
|
|
```
|
|
|
|
### [Bun Install Limitations](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#bun-install-limitations)
|
|
|
|
```
|
|
Known compatibility issues in 2026:
|
|
→ Some native binaries may not install correctly
|
|
→ Postinstall scripts: some packages assume npm/node environment
|
|
→ pnpm-specific workspace.yaml not supported (use package.json workspaces)
|
|
→ Some packages with complex resolution logic may resolve differently
|
|
|
|
Test your project before switching to Bun install in CI:
|
|
bun install && bun test # Quick compatibility check
|
|
```
|
|
|
|
* * *
|
|
|
|
## [npm: Universal Compatibility](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#npm-universal-compatibility)
|
|
|
|
```bash
|
|
# npm — the universal fallback:
|
|
npm install # Install
|
|
npm install react # Add
|
|
npm install -D typescript # Add dev
|
|
npm uninstall lodash # Remove
|
|
npm update # Update
|
|
|
|
# npm workspaces (basic):
|
|
# package.json: { "workspaces": ["apps/*", "packages/*"] }
|
|
npm install # Installs all workspaces
|
|
npm run build --workspace=apps/web # Run in specific workspace
|
|
npm run build --workspaces # Run in all workspaces
|
|
```
|
|
|
|
* * *
|
|
|
|
## [Corepack: Managing Package Managers](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#corepack-managing-package-managers)
|
|
|
|
```json
|
|
// package.json — specify exact package manager:
|
|
{
|
|
"packageManager": "pnpm@9.15.0"
|
|
}
|
|
```
|
|
|
|
```bash
|
|
# Enable Corepack (Node.js 16+):
|
|
corepack enable
|
|
|
|
# Now the packageManager field is enforced:
|
|
# If you run npm install in a pnpm project, Corepack intercepts:
|
|
# "This project requires pnpm@9.15.0. Run 'corepack use pnpm@9.15.0' to switch."
|
|
|
|
# In CI — enable Corepack before install:
|
|
corepack enable
|
|
# Then just run: pnpm install (or whatever packageManager specifies)
|
|
```
|
|
|
|
* * *
|
|
|
|
## [Decision Guide](https://www.pkgpulse.com/blog/pnpm-vs-bun-vs-npm-package-manager-performance-2026\#decision-guide)
|
|
|
|
```
|
|
Use pnpm if:
|
|
→ New project, want best practices
|
|
→ Monorepo with multiple packages
|
|
→ Strict dependency isolation important
|
|
→ Most compatible choice that's still fast
|
|
|
|
Use Bun (install) if:
|
|
→ Already using Bun as runtime
|
|
→ CI speed is critical and you've tested compatibility
|
|
→ Greenfield project with modern packages only
|
|
|
|
Use npm if:
|
|
→ Maximum compatibility needed (legacy projects)
|
|
→ Required by tooling that expects npm conventions
|
|
→ Team unfamiliar with pnpm/Bun
|
|
→ Deploying to environment where only npm is available
|
|
```
|
|
|
|
_Compare package manager downloads on [PkgPulse](https://pkgpulse.com/)._
|
|
|
|
## Comments
|
|
|
|
### The 2026 JavaScript Stack Cheatsheet
|
|
|
|
One PDF: the best package for every category (ORMs, bundlers, auth, testing, state management). Used by 500+ devs. Free, updated monthly.
|
|
|
|
Get the Free Cheatsheet |