Let me explain the concept of hoisting in package managers and why pnpm has the --shamefully-hoist
option:
-
Package Hoisting in npm/yarn:
- Traditional package managers like npm and yarn use a concept called “hoisting”
- When you install dependencies, they “hoist” packages to the top-level
node_modules
directory whenever possible - This means that if package A and package B both depend on package C, there will be only one copy of C in the top-level
node_modules
- This saves disk space but creates what’s called a “flat” dependency structure
-
pnpm’s approach:
- pnpm uses a fundamentally different approach with a strict dependency structure
- It keeps dependencies in a content-addressable store and uses symlinks
- Each package can only access dependencies it has explicitly declared
- This creates a more accurate node_modules tree that matches the actual dependency graph
- It prevents the “phantom dependency” problem (when code uses packages not declared in package.json)
-
Why
--shamefully-hoist
exists:- Some packages are written with the assumption that dependencies will be hoisted (the npm/yarn way)
- These packages might try to access modules they haven’t declared as dependencies
- The
--shamefully-hoist
flag forces pnpm to mimic npm’s hoisting behavior - It’s called “shamefully” because it sacrifices pnpm’s correctness guarantees for compatibility
-
When you might need it:
- When working with older packages that weren’t written with pnpm in mind
- When dealing with packages that have implicit dependencies
- With tooling that expects a flat node_modules structure