Enabling and Using Yarn Plug’n’Play (PnP) in Yarn 2+ Projects
Yarn Plug’n’Play (PnP) replaces node_modules with a virtual file system, speeding installs and eliminating duplicates. This guide shows how to enable strict PnP, explains the underlying mechanism, highlights limitations, and offers practical verification steps.
15 Sept 2026, 18:21 UTC

Why Yarn PnP Matters
Yarn’s Plug’n’Play (PnP) replaces the traditional node_modules directory with a virtual file system that maps module imports to exact locations in the dependency graph. The result is a single source of truth for every package, no duplicate modules, and faster installs. If you want a lean, reproducible environment, PnP is the feature to enable.
Quick Checklist to Turn PnP On
- Make sure you’re running Yarn Berry (v2 or v3).
yarn set version berrywill upgrade the CLI if needed. - Create or edit
.yarnrc.ymlin the project root and addpnpMode: strict. - Remove any existing
node_modulesfolder to avoid confusion. - Run
yarn install– a.pnp.cjsfile will appear andnode_moduleswill be absent. - Run a simple script to verify that imports resolve correctly.
Concrete Example
Assume a fresh Node.js project. The following steps illustrate the full flow.
# 1. Ensure Berry CLI
$ yarn set version berry
# 2. Configure PnP
$ cat > .yarnrc.yml <<'EOF'
pnpMode: strict
EOF
# 3. Clean any legacy node_modules
$ rm -rf node_modules
# 4. Install dependencies
$ yarn install
# 5. Verify PnP file
$ ls -la .pnp.cjs
# 6. Test import
$ node -e "import _ from 'lodash'; console.log(_.chunk([1,2,3,4], 2));"
After step 4, you’ll see a single .pnp.cjs file and no node_modules directory. The runtime will consult the virtual file system defined in that file to locate lodash.
How the Virtual File System Works
- Dependency Graph – Yarn builds a tree of all packages and their versions.
- Exports Field – Packages must expose an
exportsfield inpackage.jsonso PnP knows which entry points are valid. - PnpFallback – For packages that rely on
fs-based resolution (e.g., native addons), you can add apnpFallbackentry pointing to the real file path. - Runtime Hook – Node’s module loader is patched via
.pnp.cjsto redirect imports to the correct package location.
Limitations & Common Pitfalls
- No
node_modulesMeans Some Tools Fail – Linters, bundlers, or IDEs that scan fornode_modulesmay throw errors. Configure them for PnP or use thepnpFallbackapproach. - Native Modules – Packages that compile native code (e.g.,
node-sass) require apnpFallbackor a patchedpackage.jsonto expose the compiled binary. - Legacy Scripts – Running
yarn install --no-lockfileskips PnP generation; always use the defaultyarn install. - Mixing Yarn 1 and Berry – Do not use
yarn installfrom Yarn 1 in a Berry repo; it will create anode_modulesfolder and break resolution. - Strict vs. Loose –
pnpMode: looseallows fallback tonode_modulesfor legacy packages, but it defeats the purpose of strict dependency isolation.
Practical Verification Steps
- Check Yarn Version –
yarn --versionshould show 2.x or 3.x. - Validate PnP File –
file .pnp.cjsshould exist andnode_modulesshould be absent. - Run a Test Import –
node -e "import _ from 'lodash'; console.log(_.sum([1,2,3]));"should print6without errors. - Test a Tool with Fallback –
yarn dlx eslint .runs ESLint in a PnP-aware environment. If it fails, add apnpFallbackfor the tool’s package. - Inspect the Dependency Graph –
yarn why lodashwill show the exact version and location resolved via PnP.
When to Use pnpMode: loose
For projects that still rely on tools that cannot yet be PnP-aware, loose mode provides a safety net by falling back to node_modules when a package cannot be resolved. However, it introduces duplication and defeats some of the performance gains. Use it only during migration, and aim to switch to strict once all tooling supports PnP.
Conclusion
Enabling Yarn PnP is a straightforward process that yields a lean, deterministic dependency tree. By configuring .yarnrc.yml with pnpMode: strict, removing legacy node_modules, and verifying with simple imports and tool runs, you can confidently adopt PnP in production. Be mindful of native modules and legacy tooling, and use pnpFallback or loose mode only when necessary.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.