How to get rid of node_modules with Yarn Plug’n’Play
Reduce your install time up to 70%. Ask me how! 😱
First, I used Bower, which was primarily focused on the front-end world. Then, in 2015, I sadly (ok, not really) realized that Bower was dying and NPM, the default package manager for Node, was the way to go for the front-end too. It was strange for me, at first, to use NPM for other things than Node modules, but I got used to the idea and migrated seamlessly.
Finally, just one year later, Facebook gave us Yarn, a modern and blazing fast alternative to NPM. I loved it at first sight! But some things were still problematic…
Inherited problems in Yarn
Besides the speed, Yarn brought a number of advantages when compared to the NPM version at the time, such as lock files, offline mode, network resilience, checksums and others. Nevertheless, Yarn borrowed some known problems from NPM:
node_modules here, there, everywhere
For each project on your machine that uses NPM or Yarn, a
node_modules folder is created. It doesn't matter if 10 projects use the exact same version of a given module, it will be copied over and over into each
node_modules folder of these projects.
Generating a new node_modules folder takes a really long time
Even taking a great leap forward in terms of installation speed, Yarn was constrained by node_modules limitations. Just creating the node_modules folder takes up to 70% of the time needed to run
yarn install (with a warm cache). It's a huge amount of files to be created on every installation. So, don't blame it on Yarn.
Dependencies not added to package.json
Here’s a scenario for you: Your app works perfectly in development, but crashes in production. After hours of investigation, you finally realize that you forgot to add a dependency to your
package.json. Yes, it can happen.
Slow module resolution at runtime
The boot time of your app is heavily impacted by the way Node resolves dependencies. It wastes time querying the file system to discover where a given dependency will be resolved from.
Yarn Plug’n’Play to the rescue!
All of the above problems were addressed by the Yarn team with the release of the Plug’n’Play feature last September.
When you enable PnP, instead of copying every needed file from the cache to the
node_modules folder, here's what Yarn does:
- It creates a single file with static resolution tables. These tables will contain a bunch of important info, such as: packages available in the dependency tree, how they relate between themselves and their location on the disk.
- A special resolver is used in order to help Node discovering where each dependency has been installed (under the Yarn cache folder). It solely relies on the resolution tables which were created previously. As these tables contain information about the entire dependency tree, the node_modules resolution process won’t need to make a lot of
readdircalls at runtime anymore, significantly reducing your app boot time. And as Yarn knows all of your dependencies, it will complain if you try to import a module that's not present in your
Using Yarn Plug’n’Play
Converting a project to make use of PnP is easy as 1–2–3. You just need to add a
installConfig section to your
package.json, with a
pnp key set to
true, like this one:
Note: You need Yarn v1.12+ in order to use Plug’n’Play.
After that, just run
yarn install and everything inside your
node_modules folder will be deleted. From now on, every dependency will be resolved directly from Yarn's hot cache.
Using PnP in a new React project with create-react-app
If you use create-react-app 2+, the good news is that it works great with Yarn Plug’n’Play! Just append the
--use-pnp option to the
create-react-app command and you're good to go:
npx create-react-app your-app-name --use-pnp
As nothing is perfect in the world, PnP may incur new issues when used in projects relying on a custom install logic. If you need more info about these potential new issues, you can find a detailed explanation in this paper.
Plug’n’Play solves some really annoying problems in Yarn. Besides, it dramatically improves dependency caching on CIs, saving installation time and allowing our builds to get right to the point: running the tests!
And that’s it! Have fun with Yarn PnP.