Skip to content

Using Yarn Plug'n'Play with Nx

Plug'n'Play (PnP) is an innovative installation strategy for Node that tries to solve the challenges of using node_modules for storing installed packages:

  • slow installation process
  • slow node runtime cold start
  • expensive packages diffing when adding new packages
  • no ability to restrict access and enforce hoisting/nesting

Instead of using the node_modules folder, PnP creates a map from package names to hoisted package versions and creates dependency edges between packages. The packages are kept in zip archives which makes caching and restoring faster.

Read more about PnP on Yarn's official docs.

When you run create-nx-workspace with the optional --pm=yarn flag, Nx uses the default yarn version set in your global .yarnrc.yml file (usually in the root of your user folder). To check your current yarn version, run:

yarn --version

If the version is in the 1.x.x range, the workspace will be created with yarn classic. To migrate an existing yarn classic workspace to the modern version of yarn, also known as Berry, run:

~/workspace
yarn set version stable

This command will update .yarnrc.yml with the path to the local yarn bin of the correct version and will set the packageManager property in the root package.json:

package.json
{
// ...
"packageManager": "yarn@3.6.1"
}

Once you are on the modern version of yarn, you can use the following command to switch to PnP:

~/workspace
yarn config set nodeLinker pnp

Your .yarnrc.yml will now have nodeLinker set to a proper method:

.yarnrc.yml
nodeLinker: pnp

Once the config is changed you need to run the install again:

~/workspace
yarn install

Running install generates a .pnp.cjs file that contains a mapping of external packages and strips all the packages from the node_modules.

When using Yarn Berry, Nx will set the nodeLinker property to a backward compatible node-modules value by default. This is to ensure your repository works out of the box.

Some packages come with broken dependency requirements so using strict PnP can lead to broken builds. This results in errors similar to the one below:

yarn nx build my-project
Error: [BABEL]: @babel/plugin-transform-react-jsx tried to access @babel/core (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound.
Required package: @babel/core

The problem above is something we need to fix by ensuring the requested peer dependency exists and is available:

~/workspace
yarn add -D @babel/core

Sometimes, simply adding a missing package doesn't work. In those cases, the only thing we can do is contact the author of the package causing the issues and notify them of the missing dependency requirement. The alternative is to switch back to using the node-modules node linker.