npm vs pnpm vs Yarn
Choose a package manager from the repository's dependency model, tooling compatibility, CI workflow, and maintenance requirements. Install speed and disk use matter, but measure them on a representative project after confirming that resolution, builds, and tests preserve the required behavior.
This comparison uses modern Yarn; Yarn Classic is a different version family with different defaults. Record the exact manager and Node versions before comparing commands or interpreting an existing lockfile.
TL;DR
- A manifest declares dependency intent; a lockfile records the selected resolution in a manager-specific format.
- pnpm's linked layout and modern Yarn's Plug'n'Play mode expose dependency-access assumptions that a hoisted layout can conceal.
- Yarn supports installation modes beyond PnP, so evaluate the chosen mode rather than the product name alone.
- Use CI's frozen or immutable workflow to reject unintended lockfile changes, then verify the application actually builds and runs.
- Benchmark cold and warm installs separately, including storage, scripts, cache state, and the full pipeline rather than a single stopwatch number.
Quick Example
Create a disposable demo directory with sibling local-math and app folders. This local-only package makes dependency resolution observable without borrowing a public package's behavior.
Save local-math/package.json:
Save local-math/index.cjs:
Save app/package.json:
Save app/check.cjs:
Choose one installed manager and run its commands from app. To compare managers, use a separate clean copy of the complete demo tree for each, rather than mixing their generated files in one directory. If the Yarn copy sits beneath another Yarn project, use a separate project location or create an empty app/yarn.lock to mark its independent project boundary before installing.
Expected behavior is the printed success message. Next, in a disposable variant, change the declared dependency path to a different local package without updating the lock. Verify that the locked reinstall fails rather than silently accepting new resolution. Restore the manifest afterward.
This exercise checks resolution, execution, and lockfile enforcement for a tiny local dependency. It is not a registry, native-build, monorepo, security, or performance benchmark. In a real project, installation may run dependency lifecycle scripts; review and govern those separately.
Core Concepts
Resolution and layout are separate
Two installations can select similar package versions while exposing them differently to Node and build tools. A traditional node_modules hierarchy, pnpm's linked store layout, and a PnP loader are different implementation choices.
The pnpm structure guide describes files linked from its content-addressable store and symlinks representing the dependency graph. This can avoid duplicating package content, but actual disk savings depend on the filesystems, projects, caches, and configuration being measured.
Modern Yarn PnP uses a loader describing package locations instead of requiring a traditional node_modules tree. Yarn also supports other install strategies. Check whether the project's bundler, editor, runtime launcher, and native dependencies support the selected strategy.
Declared dependencies matter
A package should declare the dependencies it directly uses. If it imports an undeclared dependency merely because another package caused that dependency to be hoisted into reach, a different install layout can reveal the mistake.
Treat a migration failure as evidence to investigate, not immediate proof that the manager is broken. It may expose an undeclared dependency, an unsupported resolver assumption, or a real compatibility limitation. Fix the contract or choose a supported layout deliberately instead of enabling broad hoisting until every unexplained error disappears.
Lock enforcement is a workflow contract
npm ci requires an appropriate lockfile and does not update the manifest or lock during installation. pnpm's frozen mode and Yarn's immutable mode reject installations that would require lockfile changes under their documented conditions.
A committed lockfile is useful only if the pipeline enforces it and records the manager configuration that affects resolution. It does not establish that every dependency is safe, that a lifecycle script is harmless, or that arbitrary platform differences disappear.
Workspaces and Migration
All three provide workspace support: npm, pnpm, and Yarn. Compare package linking, task execution, publication conventions, and the configuration supported by the exact versions in your repository. Do not assume their workspace protocols or configuration files are interchangeable.
Before migration, inventory workspace boundaries, direct imports, registry/authentication settings, patches, overrides, native builds, scripts, and CI caches. Keep credentials out of the comparison artifacts. A cache key that ignores manager or lockfile identity can make a supposedly clean test reuse incompatible output.
Pilot in a branch or disposable copy. Create the new manager's reviewed lockfile, install from a clean environment, and run the actual build, test, lint, packaging, and representative runtime paths. Include editor integration and deployment packaging when the install mode affects how dependencies are loaded.
Once the selected path works, update the repository's documented commands, manager-version pinning mechanism, CI jobs, and cache rules together. Remove obsolete lockfiles only as an intentional reviewed migration change. Retain a rollback plan until the target deployment path has been exercised.
Measure Speed and Disk Use Fairly
Define a cold install precisely: empty manager store, empty project install output, or simply a new project directory are different states. A warm store can avoid network transfer while a warm project may avoid most linking work. Record which state was used for every observation.
Measure the same dependency graph on the same platform, with the same lifecycle-script policy and comparable network conditions. Report several runs and explain variation rather than presenting an isolated result as a universal ranking.
For disk use, distinguish the project directory, shared store/cache, and actual allocated space. Counting apparent file sizes can misrepresent shared links or compressed cache artifacts. Include cleanup and cache maintenance in the operating picture.
Finally, time the full workflow. Saving installation time can be worthwhile, but a resolver compatibility issue that delays builds or incident response can outweigh that gain. Choose from the total constraint, not whichever command produces the most satisfying terminal progress bar.
Best Practices
Pin the workflow, not just the lockfile
Document the selected manager, version, Node runtime, and relevant install mode. Use the project's approved version-management mechanism and check it in CI so developers and release jobs run the same workflow.
Test one deliberate failure
Change a dependency declaration in a disposable variant and verify the locked install rejects it. A successful install alone does not prove enforcement is active.
Separate trust from reproducibility
Review package sources, scripts, credentials, and publishing permissions independently of lockfile correctness. A reproducibly installed malicious dependency remains malicious.
Common Mistakes
Bad: Declare a universal speed winner from a warm-cache demo.
Correct: State project, platform, cache state, configuration, and measurement method; compare the full pipeline.
Bad: Mix managers and regenerate whichever lockfile happens to change.
Correct: Select one repository workflow and make migration or multi-manager support an explicit maintained decision.
Bad: Treat PnP or pnpm compatibility errors as permission to ignore missing declarations.
Correct: Investigate imports and tooling assumptions, then fix dependencies or choose a supported installation mode.
FAQ
Is pnpm always faster than npm?
No universal result follows from the storage design. Measure the actual graph, cache states, scripts, platform, and pipeline requirements.
Does modern Yarn require PnP?
PnP is its documented default strategy, but other installation modes are supported. Record and test the selected mode.
Can all three manage a monorepo?
All provide workspace support. Compare the specific linking, execution, packaging, and publishing workflow your monorepo needs.
Can I keep the old lockfile during a migration pilot?
Keep the baseline recoverable while experimenting in an isolated copy or branch. Before adopting the new workflow, deliberately resolve which lockfiles and commands the repository will maintain.
Related Topics
- Yarn — Cover workspaces, dependency protocols, Plug'n'Play, constraints, and team migration workflows.
- Package Managers — Understand dependency and installation responsibilities.
- npm — Review manifest, script, and package trust boundaries.
- pnpm — Explore its dependency layout and workflow.
- Software Supply Chain Security — Separate trusted input from repeatable installation.