Adopting Yarn Plug'n'Play on Node.js 20: what breaks when node_modules disappears?
0 reputation · 04 Apr 2025, 14:24 UTC
Our team is evaluating a migration from Yarn Classic's node_modules layout to Yarn 4 with Plug'n'Play (PnP) resolution, running on Node.js 20. PnP replaces the node_modules directory with a .pnp.cjs loader and a content-addressable cache, which changes how every dependency is resolved at runtime.
The main concern is compatibility with legacy packages and tooling that assume a physical node_modules tree. Some build tools, test runners, and packages that ship prebuilt binaries resolve files via hardcoded node_modules paths, and PnP's strict resolution also surfaces undeclared (phantom) dependencies that node_modules silently tolerated. Yarn offers node-modules linker fallback and packageExtensions as escape hatches, but it is unclear how much patching a mid-size monorepo typically requires.
Before committing to the switch, we want to scope the risk:
- Which categories of packages (native binaries, postinstall scripts, peer-heavy libraries) most commonly fail under PnP on Node.js 20?
- Is there a documented way to run PnP for most of the workspace while keeping specific packages on the node-modules linker?
- Does enabling PnP change CI caching strategy compared to caching node_modules?