codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›tools

pnpm

Published 2026-04-28· Updated 2026-05-18·0 views

pnpm

pnpm is one of the package managers in the Node.js ecosystem. This article covers pnpm's origins, how it works, and how it differs from other managers — based on facts.

1. About pnpm

Short for "performant npm", an open-source project started by Zoltan Kochan in 2017. The copyright reads "2015–present contributors of pnpm" — early experiments started in 2015 in the GitHub repo (pnpm/pnpm), reached 1.0, and continue today through 9.x and 10.x major versions. License is MIT.

The two problems it set out to solve:

  • npm's behavior of installing the same package across many projects, filling up disk fast.
  • The "phantom dependency" problem, where a flattened (hoisted) node_modules lets code import dependencies that were never declared.

2. How it works

pnpm's core is a content-addressable store. Package files are stored once in ~/.pnpm-store (or the OS default path), and each project's node_modules holds hard links pointing to those files. When many projects depend on the same library version, only one copy lives on disk.

The node_modules layout has two layers:

  • node_modules/.pnpm/<pkg>@<ver>/node_modules/<pkg> — the real package (hard-linked from the store).
  • node_modules/<direct-dep> — a symlink to the path above.

Only directly declared dependencies are exposed at the top level, so code cannot require a module that isn't listed in package.json. The official docs call this "non-flat node_modules".

3. Workspaces

A pnpm-workspace.yaml at the root with package path patterns:

packages:
  - "apps/*"
  - "packages/*"

Internal dependencies are written with a protocol like "workspace:*" to point inside the workspace instead of the external npm registry.

pnpm-lock.yaml records exact versions and hashes for every dependency — a commit target.

4. Other paths

Tool First release Trait
npm 2010 Bundled with Node.js. Flattened node_modules. Widest compatibility.
Yarn Classic (1.x) 2016 From Facebook. Introduced lockfile and workspaces ahead of npm. Now in maintenance mode.
Yarn Berry (2+) 2020 A PnP (Plug'n'Play) mode that drops node_modules entirely. Adoption splits over tooling compatibility.
pnpm 2017 Store + hard / symlinks. Disk savings and strict dependencies.
Bun 2023 (1.0) Zig-based runtime + package manager. bun install speed is its strength.

The right fit depends on the environment. If CI assumes only standard Node tooling, npm; where disk savings and monorepo isolation matter, pnpm; for greenfield projects where speed is the priority, Bun.

5. Common shapes

# Install
# Windows: PowerShell
iwr https://get.pnpm.io/install.ps1 -useb | iex
# macOS · Linux: bash
curl -fsSL https://get.pnpm.io/install.sh | sh -

# In a project
pnpm install            # install dependencies
pnpm add zod            # add a runtime dependency
pnpm add -D vitest      # dev dependency
pnpm remove zod
pnpm update
pnpm run build          # or just pnpm build

Running a command for a specific package from the workspace root:

pnpm --filter web dev
pnpm -r build           # run build in every workspace package

6. engines · packageManager

A common convention is to pin Node and pnpm versions in package.json:

{
  "engines": {
    "node": ">=20.10",
    "pnpm": ">=9"
  },
  "packageManager": "pnpm@9.12.3"
}

Corepack (bundled with Node 16.10+) reads the packageManager field and prepares the matching manager version automatically.

7. Common pitfalls

phantom dependency — some tools assume a flattened node_modules and rely on phantom dependencies, which breaks under pnpm. Usually the fix is to declare the missing dependency in package.json. A workaround is shamefully-hoist=true in .npmrc, but it muddies intent.

Windows hard links — when the user profile sits on a different drive, hard links only work within the same volume. The store has to move to the same drive as the project. Use PNPM_HOME or pnpm config set store-dir.

Mixed lockfiles — when npm and pnpm lockfiles end up in the same repo, dependency resolution becomes shaky. Pair the packageManager field with Corepack so CI and local use the same manager.

pnpm dlx vs npx — different cache paths mean tools cached on one side may need to be re-fetched on the other.

Closing thoughts

pnpm's content-addressable store plus its non-hoisted layout deliver disk savings and phantom-dependency blocking together. The difference shows up the most in monorepos. Pin versions team-wide and CI-wide with the packageManager field plus Corepack.

Next

  • monorepo-light
  • python-uv

References include the official pnpm docs, pnpm motivation, pnpm GitHub, npm Documentation, Yarn Documentation, Node.js Corepack, and the pnpm blog.

More in tools

All in this category →
  • Git Submodule · Subtree · LFS — repos inside repos
  • Regular expressions — finding strings by pattern
  • A history of Python dependency tools
  • Linting and formatting
  • Editor setup
  • Gradle