Decision Guide: Yarn PnP vs Classic Install for Monorepos
Learn how to decide between Yarn PnP and classic node_modules installs in a monorepo, compare trade‑offs, and verify the chosen layout with concrete commands.
25 Feb 2026, 20:59 UTC

Decision and constraints
When setting up a monorepo with Yarn, you must decide how dependencies are laid out on disk. The choice affects disk usage, tool compatibility, and runtime behavior of native modules.
Supported options
| Option | How it works | Typical use case | Considerations |
|---|---|---|---|
| Yarn PnP (Plug'n'Play) | All packages are stored in a central .yarn/cache content‑addressed store; a .pnp.js file maps module requests to that store without a node_modules folder. | Projects that want minimal disk footprint and can tolerate tools that need a virtual file system. | May break native add‑ons or scripts that expect a physical node_modules path. |
| Classic install (node_modules) | Each workspace gets its own node_modules folder (or a shared one when workspaces hoist to the root). Dependencies are unpacked as regular files and symlinks. | Repos that rely on scripts, binaries, or native add‑ons expecting a physical node_modules path. | Can duplicate copies across workspaces unless hoisted. |
| Workspaces with hoisted node_modules | Yarn workspaces can hoist matching dependencies to the root node_modules, reducing duplication while keeping a classic layout. | Monorepos where most packages share the same version of a dependency and you still need a node_modules folder. | Hoisting can cause hoisting‑related conflicts if versions diverge. |
Trade‑offs
- Disk usage: PnP stores each version once in the cache; classic install may duplicate copies across workspaces unless hoisted.
- Tool compatibility: Tools that resolve modules via the file system (e.g., some native add‑ons, certain CLI utilities) expect a node_modules directory and may fail with PnP unless a polyfill like pnpify is used.
- Native modules: PnP can break binary add‑ons that look for ./node_modules/.bin or try to load ../build/Release/module.node relative to a node_modules folder.
- Resolution control: Yarn resolutions work identically in both layouts, letting you enforce a single version across the monorepo.
Concrete implementation
Below is a minimal example showing how to enable PnP in an existing Yarn 2+ workspace and verify the layout.
-
Ensure you are using Yarn 2 or later (PnP is the default from Yarn 2). Run:
# Run in the repository root yarn --versionExpected output: a version string starting with 2. or 3.
-
If you are currently using Yarn 1.x, upgrade:
# Requires write access to the repository curl -fsSL https://yarnpkg.com/getyarn.sh -o- | bash -s -- --version 2.0.0After upgrading, commit the new .yarn/releases folder.
-
Enable PnP explicitly (optional in Yarn 2+):
yarn config set nodeLinker pnp -
Install dependencies:
yarn installAfter completion, check for the presence of the PnP artifacts:
- .pnp.js in the repository root
- .yarn/cache directory containing compressed packages
- Absence of a node_modules folder at the root (unless a workspace explicitly opts out)
-
Validate that a typical package can resolve its dependencies:
# From any workspace node -p "require.resolve('lodash')"If the command returns a path inside .yarn/cache, PnP is working.
Limitations and verification
- Some plugins (e.g., certain versions of electron-rebuild) expect a node_modules folder and will fail with PnP. In such cases, either:
- Add the offending package to nohoist in the workspace package.json to keep a classic node_modules for that workspace, or
- Use the pnpify shim to create a virtual node_modules.
- To verify that a workspace is using the classic layout instead, run
yarn config set nodeLinker node-modulesfollowed byyarn installand look for a node_modules folder. - Disk usage can be inspected with
du -sh .yarn/cacheversusdu -sh node_modules(if present).
By following the steps above you can confidently choose the layout that matches your tooling constraints while gaining the benefits of Yarn’s workspace management.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.