One Yarn to Rule Them All
How to enforce a specific Yarn version across your whole project
At productboard, we rely heavily on Yarn — a fast, reliable, and secure package manager. For those of you who know the ecosystem, it will be pretty obvious how yarn.lock has helped us improve confidence in our projects’ dependencies. For the rest of you, here’s a clue from the official documentation:
Your yarn.lock file ensures that your package is consistent across installations by storing the versions of which dependencies are installed with your package.
In other words, this means you can be sure that you are working with the same dependencies (and their dependencies) as your colleagues. The same also applies to the CI systems we are using.
Sounds good, right? Sure! But things aren’t always so straightforward. Different versions of Yarn may produce a different yarn.lock. This happened to me when Yarn introduced the integrity field.
When this happens, you might end up requesting changes to your colleagues’ PR to upgrade their Yarn accordingly and regenerate the file to keep the diff clean.
So what now? Should we update the main Readme with the supported version of Yarn? No! We can go one better…
Enforcing the specific version
One way to enforce a version within one project is to use the engines field in package.json (see documentation).
{ "engines": { "yarn": "1.21" } }
This allows you to enforce a specific version of yarn for everyone who will run Yarn commands including add, for example.
In this case, when you try to install a new package, you may get this message.
That’s better. But still, you need to install the requested version manually. Now, let’s imagine that the recommended version will change — you would have to repeat the process again! Frustrating, eh? Don’t worry, there’s a better way…
One Yarn for everyone
This headline may sound silly but bear with me. The authors of Yarn have been facing this specific issue themselves. Thankfully, they’ve come up with a great solution.
Ladies and gentleman, allow me to introduce the best way to keep your Yarn version aligned across the team: yarn policies.
What is Yarn policies all about?
yarn policies set-version offers a simple way to check in your Yarn release within your repository. Once you run it, your configuration will be updated in such a way that anyone running a Yarn command inside the project will always use the version you set.
And how do I use it?
yarn policies set-version
This command will set the latest stable Yarn as the default for everyone working in the same repository. It’s as simple as that.
A Yarn binary snapshot will be stored within .yarn/releases along with the updated yarn-path in the .yarnrc configuration file. Now, you’ll be using the locally “installed” version of Yarn.
And last but not least, make sure to push these changes to your remote, so everyone within the team gets the same benefits — one exact, locally scoped version of Yarn, no matter what version they have installed. No more yarn.lock deviations! Beautiful.
Final touches
If you’re using GitHub, you might be familiar with the language distribution dashboard. This is how our repository looked before we introduced the change I just walked you through. Let’s say you’re using TypeScript, as we do.
And this is how it looks after I merged my lovely changes.
Wait, what? Allow me to explain…
GitHub uses a program called Linguist to calculate code distribution. And by default, it processes all the versioned files.
Thankfully, you can control this process. Simply edit your .gitattributes as follows to ignore this file from the graph.
.yarn/releases/*.js linguist-vendored
And that’s it! If it’s not versioned, it didn’t happen!
Kudos to Martin Hochel for proofread!