Yarn Berry and Plug'n'Play

Yarn 2 11,798 arrived in January 2020; Yarn 4 (October 2023) reached 4.18.1 in September 2026. Its default install strategy is Plug'n'Play (PnP). Instead of Node walking up the tree through node_modules folders, PnP keeps each package as a zip in Yarn's cache and writes one file, .pnp.cjs, mapping every package to its location and to the dependencies it may see (2).

Classic node_modules resolution walks the disk; Plug'n'Play looks up a map
Classic node_modules resolution walks the disk; Plug'n'Play looks up a map
Installing BookNest with Yarn Berry and resolving through the PnP mapShell
mkdir ~/v5-ch1/yarn-demo && cd ~/v5-ch1/yarn-demo
cp -r ../booknest/{package.json,app.js,server.js,db,public,test} .
yarn install
ls -A | xargs
yarn node -e 'console.log(require.resolve("express"))'
yarn node -e 'require("debug")'
Output
➤ YN0000: · Yarn 4.18.1
...
➤ YN0013: │ 29 packages were added to the project (+ 1.56 MiB).
...
➤ YN0000: · Done in 4s 569ms
.pnp.cjs .yarn app.js db package.json public server.js test yarn.lock
/home/dev/.yarn/berry/cache/express-npm-5.2.1-d1e97b99e1-10c0.zip/node_modules/express/index.js
...
Error: Your application tried to access debug, but it isn't declared in your dependencies; ...
Required package: debug
Required by: /home/dev/v5-ch1/yarn-demo/

There is no node_modules, and 54 of the 83 packages came from Yarn's global cache. Code runs through yarn node or a script (yarn start), which loads the map first; Express 24,430 then loads straight out of a zip. The last command asks for debug, which Express uses but BookNest never declared. npm 2,036 hoisted debug to the top of node_modules, so there it would work: a phantom dependency that breaks the day Express drops debug. PnP refuses it at once. The price is setup: editors need yarn dlx @yarnpkg/sdks, and packages with undeclared dependencies need packageExtensions in .yarnrc.yml.