What is Yarn 2?
Why did we need a new Yarn version?
Whether you’re a fan of monorepos or not, managing them requires a good set of toolchains to ensure the success and pain-free of managing large projects and complicated workflows.
A popular recipe for setting up monorepo for JavScript projects is the combination of Yarn’s workspaces (existed since Yarn 1) and Lerna as a project manager.
The good news with Yarn 2 is that now, Yarn doubles as being both a package manager as well as a project manager and aims to provide a wholesome experience for running monorepos smoothly.
What hasn’t been said on node_modules? The new Yarn docs go into further details about the shortcomings of node_modules as a folder structure and iterate why a new way of thinking about how we manage dependencies is needed.
An interesting security angle with how Yarn 2 implements Plug’n’Play:
- The local cache folder .yarn/cache is mounted as read-only and so it doesn’t allow malicious attempts to modify already installed packages on the file system.
- Due to the nature of Plug’n’Play with Yarn, it is able to apply strict checks, such as disallowing packages to refer to so-called phantom packages that aren’t defined within a package or project’s list of dependencies.
Perhaps this is more of a developer/maintainer perspective rather than the end-user’s but still important to capture. When building Yarn 2 with TypeScript, the opportunity arose for also decreasing the complexity and maintenance of the very core, by creating a plugin architecture that allows for others to extend Yarn.
Even more features?
How to get started with Yarn 2?
Yarn has adopted a per-repository — or per-project if you will — install strategy which means you can have one global install of Yarn — such as the first, classic version of Yarn — and then shift to Yarn 2 for a specific project.
Getting started with Yarn 2 requires you to have an up to date version of Node.js, at minimum Node.js 10. In any case, Node.js LTS should always be your preferred version since it is supported and maintained. Node.js versions prior to 10 are not supported anymore and so no bug fixes, and no security fixes.
Switching to the new Yarn version
To get started, we’ll create a new directory to init a new project:
mkdir my-app cd my-app
Let’s find out your current Yarn version with
yarn --version. if you’re running a Yarn version below 1.22 go ahead and type-in:
yarn policies set-version berry
If your local Yarn version is 1.22 and above:
yarn set version berry
This should fetch Yarn 2 and show you an output as follows:
Resolving berry to a url... Downloading https://github.com/yarnpkg/berry/raw/master/packages/berry-cli/bin/berry.js... Saving it into /private/tmp/my-app/.yarn/releases/yarn-berry.js... Updating /private/tmp/my-app/.yarnrc... Done!
You can then verify your version of Yarn with yarn –version, for me it shows:
As usual, it is advised to commit .yarnrc and .yarnrc.yml to share configuration across the repo. It’s interesting to note here the use of .yarn folder where yarn manages cache, the yarn runtime, plugins and other data.
Updating the policy for Yarn 2 downloads a copy of the latest release into the local
.yarn/ folder and creates a
.yarnrc which records the path on disk to the installed version.
Installing npm modules in Yarn 2
Let’s add the Node.js web framework Fastify to our dependencies:
yarn add fastify ➤ YN0000: ┌ Resolution step ➤ YN0000: └ Completed in 2.45s ➤ YN0000: ┌ Fetch step ➤ YN0013: │ string-similarity@npm:4.0.1 can't be found in the cache and will be fetched from the remote registry ➤ YN0013: │ string_decoder@npm:1.3.0 can't be found in the cache and will be fetched from the remote registry ➤ YN0013: │ tiny-lru@npm:7.0.2 can't be found in the cache and will be fetched from the remote registry ➤ YN0013: │ uri-js@npm:4.2.2 can't be found in the cache and will be fetched from the remote registry ➤ YN0013: │ util-deprecate@npm:1.0.2 can't be found in the cache and will be fetched from the remote registry ➤ YN0000: └ Completed in 1.73s ➤ YN0000: ┌ Link step ➤ YN0000: └ Completed in 0.07s ➤ YN0000: Done in 4.26s
You can already see some changes in Yarn’s new output:
- Every set of related tasks that happens in the install process is grouped together.
- Yarn provides a reference in the CLI output to each group of tasks so if you have an issue with one of them, it is easier to troubleshoot.
The lock file is still the preferred way of how Yarn manages pinning dependencies for repeatable and auditable versions of dependencies. New in Yarn 2, however, is that it is now a proper YAML syntax.
The common package management commands have remained the same with prior Yarn versions:
yarn add [package] --dev
yarn remove [package]
yarn up [package]
Now that there’s no node_modules directory anymore, running a one-off script such as
node script.js won’t work as it won’t be able to resolve the dependencies stated in that file. For that reason, you need to issue
yarn node script.js in which yarn will spawn the node process with its own file that patches some of the logic to allow the PnP magic. It does so by using Node’s built-in
--require CLI flag.
Also note that
yarn node isn’t required inside scripts defined in the
scripts field (which is how a lot of tools are invoked anyway), just calling
node is enough. Thanks Mael for clarifying this! 🤗
I suggest heading over to Yarn’s website for the elaborate documentation at https://yarnpkg.com/cli/install as you try it out with your next project.