npm vs Yarn vs pnpm: Which JavaScript Package Manager Wins in Speed and Space?

This article traces the evolution of JavaScript package managers—from early manual inclusion methods to npm, Yarn, and pnpm—detailing their architectures, performance characteristics, version‑locking mechanisms, and trade‑offs, helping developers choose the most suitable tool for modern frontend projects.

Goodme Frontend Team
Goodme Frontend Team
Goodme Frontend Team
npm vs Yarn vs pnpm: Which JavaScript Package Manager Wins in Speed and Space?

Introduction

Package managers exist for many languages; in modern frontend development tools like npm, Yarn, and pnpm simplify dependency management and improve development efficiency. This article analyzes the history and current mainstream tools, comparing their advantages and suitable scenarios.

Ancient Times

Before Node.js, third‑party resources such as jQuery were added by downloading zip files or linking via CDN, leading to version chaos, large project size, and broken dependencies. The emergence of Node.js and its modular system introduced npm, initially for server‑side packages but later adopted by the frontend community.

Package Manager Evolution

npm

npm before v3

Released in July 2011, npm 1.0 stored dependencies in a deeply nested node_modules structure, causing large folder size, deep nesting, and slow installation.

node_modules
└─ foo
   ├─ index.js
   ├─ package.json
   └─ node_modules
      └─ bar
         ├─ index.js
         └─ package.json

Problems

Huge node_modules size due to duplicated packages.

Excessive nesting leading to long paths and Windows deletion issues.

Serial installation makes the process slow.

npm v3 (flattening)

npm v3 introduced a flattening strategy that reduces nesting by hoisting shared dependencies to the top level.

node_modules
├─ foo
|  ├─ index.js
|  └─ package.json
└─ bar
   ├─ index.js
   └─ package.json

While flattening mitigates some duplication, it does not fully resolve multiple version installations and can introduce “ghost” dependencies.

Remaining Issues

Duplicate installations still occur.

Ghost dependencies may appear without being declared in package.json.

No offline cache mode, leading to slower installs.

Yarn

Yarn was created to address npm’s shortcomings, especially consistency and speed.

Version lock for consistency

Yarn introduced yarn.lock, which records exact versions of all dependencies; npm later added package-lock.json with similar goals.

Differences in flattening

// Example dependency tree
node_modules
├─ htmlparser2@^3.10.1
|  └─ entities@^1.1.1
└─ dom-serializer@^0.2.2
   └─ entities@^2.0.0

Yarn’s lock file stores a flat, deterministic description of each dependency, merges compatible semver ranges, and uses a stricter resolution algorithm, ensuring identical installations across environments.

SemVer support

Both npm and Yarn follow Semantic Versioning (MAJOR, MINOR, PATCH) to communicate breaking changes, new features, and bug fixes.

Yarn advantages

Global cache and offline installation.

Parallel, multi‑threaded installation.

More stable version locking.

pnpm

Why pnpm is considered advanced

pnpm aims to save disk space, speed up installations, and keep a non‑flattened node_modules layout.

Disk‑space savings

Dependencies are stored in a content‑addressable store and linked into projects via hard links, so only one copy of each version exists.

Installation speed

pnpm downloads each package once and installs dependencies in parallel, reducing overall time.

Non‑flattened node_modules

pnpm creates a symlinked structure that isolates each package’s dependencies while keeping a flat resolution graph.

-> - a symlink (or junction on Windows)

node_modules
├─ foo -> .registry.npmjs.org/foo/1.0.0/node_modules/foo
└─ .registry.npmjs.org
   ├─ foo/1.0.0/node_modules
   |  ├─ bar -> ../../bar/2.0.0/node_modules/bar
   |  └─ foo
   |     ├─ index.js
   |     └─ package.json
   └─ bar/2.0.0/node_modules
      └─ bar
         ├─ index.js
         └─ package.json

Limitations

npm‑shrinkwrap.json and package‑lock.json are ignored; conversion requires pnpm import.

Binstubs in node_modules/.bin are shell scripts, not symlinks to JS files.

Conclusion

npm, Yarn, and pnpm are all capable package managers; the choice depends on project needs and personal preference. npm integrates tightly with the Node.js ecosystem, Yarn offers faster installs and reliable lock files, while pnpm focuses on disk‑space efficiency and speed.

frontend developmentNode.jsPackage ManagerpnpmnpmYaRN
Goodme Frontend Team
Written by

Goodme Frontend Team

Regularly sharing the team's insights and expertise in the frontend field

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.