Plate 12
Yarn Berry vs pnpm: 1.3s vs 0.24s Install
Yarn 4.9.2 (Berry PnP + node-modules linker) vs pnpm 12.9.1 on one 22-dependency React+Vite app. Isolated caches (Yarn enableGlobalCache false; pnpm --store-dir). Warm medians (5): Yarn PnP 1.307 s, Yarn nm 2.471 s, pnpm 0.240 s. Lock+empty medians 1.656 / 2.789 / 0.725 s. Clean disk: Yarn PnP 246 MB; Yarn nm modules 189 MB; pnpm hardlink project 167 MB. Fixture /workspace/bench-yarn-pnpm/. Distinct from pnpm-vs-npm-vs-bun (no Yarn).
Aditya Challa4 min read
I installed one 22-dependency React + Vite app five times with a warm local cache on this box: Yarn Berry 4.9.2 (PnP) median 1.31 s, pnpm 12.9.1 median 0.24 s — about 5.5× faster for pnpm. After install, the Yarn PnP project tree was 246 MB; the pnpm tree with an isolated store was 167 MB.
Short answer: for this app on Linux CI-style installs, pnpm won wall time and project disk. Yarn PnP still fits teams that want no node_modules. This is not a remake of the npm/pnpm/Bun three-way. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 00:30–00:40 IST.
- Versions: Yarn 4.9.2 (Berry via Corepack), pnpm 12.9.1, Node 22.20.0. Yarn enableGlobalCache false with per-project .yarn/cache. pnpm --store-dir isolated under the project; allowBuilds for esbuild under pnpm 12.
- Fixture: /workspace/bench-yarn-pnpm/. package.json with 10 runtime deps (react 19, react-dom, react-router 7, @tanstack/react-query 5, zod 4, date-fns 4, clsx, lucide-react, zustand 5, axios) and 12 devDeps (vite 6, plugin-react, typescript 5, vitest 3, jsdom, eslint 9, prettier, tailwindcss 4, @types/*, @testing-library/react). Same lockfile reused for timed rounds.
- Timing: cold first install (no lock); then 5× lock + empty local cache; then 5× lock + filled local cache (immutable / frozen). Wall times via perf_counter around the install process.
- Findings: warm medians Yarn PnP 1.307 s, Yarn node-modules linker 2.471 s, pnpm 0.240 s. Lock+empty medians 1.656 s / 2.789 s / 0.725 s. Cold first installs 2.762 s / 3.435 s / 0.700 s. Clean disk: Yarn PnP total 246 MB (cache 245 MB, .pnp.cjs ~0.6 MB, no node_modules); Yarn node-modules 189 MB modules (+209 MB cache, 398 MB total); pnpm hardlink mode 167 MB project (modules and store share inodes).
- One surprise: Yarn’s node-modules linker was slower than PnP on every warm round here; pnpm still beat both.
- Not tested: npm, Bun, Yarn 1 classic, workspaces/monorepos, Windows/macOS, offline mirror, Corepack on a locked-down PATH without COREPACK_HOME, private registries.
How wide was the install gap?
| Mode | Yarn 4 PnP median | Yarn 4 node-modules | pnpm 12 median |
|---|---|---|---|
| Warm (lock + local cache) | 1.31 s | 2.47 s | 0.24 s |
| Lock + empty local cache | 1.66 s | 2.79 s | 0.73 s |
| First cold (no lock) | 2.76 s | 3.44 s | 0.70 s |
| Disk after clean install | Size |
|---|---|
| Yarn PnP project total | 246 MB |
| Yarn node-modules folder | 189 MB |
| pnpm project total (hardlink store) | 167 MB |
Same app, isolated caches. For the npm/pnpm/Bun angle see pnpm vs npm vs Bun. For dependency drift tooling see ncu vs npm outdated and syncpack vs npm-check.
Does Yarn PnP still win anywhere?
Yes, when you want zero node_modules in the repo checkout and are ready to carry .pnp.cjs plus Zip cache semantics. On this box PnP was faster than Yarn’s own node-modules linker, but not faster than pnpm. pnpm 12 also needed an explicit allowBuilds entry for esbuild — plan for that in new projects.
Do not read this as “Yarn is slow forever”: network from the box is fast, and a different dependency set can move the medians. It is a Yarn Berry vs pnpm decision on one 22-dep app, not a third place for Bun.
Should you switch package managers?
| Situation | My pick |
|---|---|
| Default new Node app on Linux CI | pnpm |
| Need Yarn PnP (no node_modules) | Yarn Berry PnP |
| Migrating off Yarn 1 classic | Yarn Berry or pnpm; measure both |
| Already standardized on pnpm | Stay |
| Monorepo task runner next | Pair with Turbo vs Nx |
| Hunting unused packages after a move | See knip vs depcheck |
Bottom line: on one 22-dep React app, warm installs landed at 1.31 s for Yarn Berry PnP and 0.24 s for pnpm 12, with project trees at 246 MB vs 167 MB. Who should not switch: teams whose Yarn PnP toolchain (editor SDKs, patches, constraints) already pays the rent.
How this was made: I generated lockfiles on the ShopperCove box, timed interleaved Yarn 4 and pnpm 12 installs with isolated caches, measured du -sb trees, recorded JSON; the write-up was drafted with AI help and checked against that output.
Sources
- https://yarnpkg.com/
- https://yarnpkg.com/features/pnp
- https://pnpm.io/
- https://www.npmjs.com/package/pnpm
- https://nodejs.org/api/corepack.html
Related
- https://www.shoppercove.com/blog/pnpm-vs-npm-vs-bun
- https://www.shoppercove.com/blog/ncu-vs-npm-outdated
- https://www.shoppercove.com/blog/syncpack-vs-npm-check
- https://www.shoppercove.com/blog/turbo-vs-nx
- https://www.shoppercove.com/blog/knip-vs-depcheck
- https://www.shoppercove.com/blog/lefthook-vs-husky
- https://www.shoppercove.com/blog/turbo-vs-lage
- https://www.shoppercove.com/blog/changesets-vs-standard-version
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~00:30–00:40 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). Yarn 4.9.2 via Corepack (COREPACK_HOME writable) vs pnpm 12.9.1. Fixture /workspace/bench-yarn-pnpm/: 10 deps + 12 devDeps React/Vite app. Yarn enableGlobalCache false + ./.yarn/cache; pnpm --store-dir per project + allowBuilds esbuild. Warm lock+cache (5): Yarn PnP 1.307 s median (1.184–1.582), Yarn nm 2.471 s (2.422–3.434), pnpm 0.240 s (0.224–0.259). Lock+empty (5): 1.656 / 2.789 / 0.725 s. Cold first: 2.762 / 3.435 / 0.700 s. Clean du -sb: Yarn PnP total 257,530,659 B (~246 MB); Yarn nm modules 198,460,829 B (~189 MB); pnpm hardlink total 174,610,936 B (~167 MB). Raw: /workspace/bench-yarn-pnpm/res-yarn-pnpm.json + res-disk.json. Not tested: npm, Bun, Yarn 1, workspaces, Windows/macOS, offline mirror. No affiliate.
Related links
Plate 68
pnpm vs npm vs Bun: Which Installs Fastest? 14s, 3.1s, 1.5s
npm 12.2.0 vs pnpm 12.9.1 vs Bun 1.4.2 on one 24-dependency React + Vite app: from scratch 14.2 s / 3.1 s / 1.5 s; lockfile + warm cache 2.9 s / 0.28 s / 0.27 s; lockfile + empty cache 3.9 s / 2.3 s / 0.45 s. Disk, lockfile size and the pnpm phantom-dependency catch.
5 Oct 2026
Plate 95
Sharp vs imagemin: 305ms vs 399ms Encode
sharp 0.35.5 vs imagemin 9.0.1 + imagemin-mozjpeg 10.0.0 on one 1920×1080 JPEG → JPEG q80 (no resize). Warm medians (7 rounds after 1 warm-up): sharp 305 ms / 546,546 B vs imagemin-mozjpeg 399 ms / 675,128 B (~1.3×). Context: sharp resize 800 q80 median 115 ms / 142,435 B. Fixture /workspace/bench-sharp-imagemin/.
5 Oct 2026
Plate 47
bun test vs Vitest: 136ms vs 1.67s on 300 Tests
bun test 1.4.2 vs Vitest 5.0.3 on 300 TypeScript tests in 60 files: warm wall medians 136 ms vs 1,673 ms (~12x); Vitest --no-isolate 765 ms (~5.6x). A 5-file vitest-API check (vi.fn, vi.mock, fake timers, spyOn, it.each, snapshot) passed 7/7 under Bun.
5 Oct 2026