Skip to main content

Release: Yarn 2.1 ๐Ÿฑโ€๐Ÿ

ยท 9 min read
Maรซl Nison
Lead Yarn maintainer

How are you doing since January? So many things happened since then. I hope you're all safe, wherever you are.

As for today, we'll be here to talk about Yarn. And as far as Yarn goes I'm happy to report that our work continued at a very good pace! So good in fact that it's now time to release the next minor build, the 2.1 ๐ŸŽ‰

Still, don't let this little number trick you: more than 350 pull requests were merged since the previous release! This is an incredible pace for our project, only made possible by the dedicated community that gathered around our favorite tool ๐ŸŒŸ

So what's in the 2.1? Many, many things! We'll go over the main items, but a more detailed list can be found in our repository. You should check it out too, there's a lot of interesting tidbits!

Don't know how to upgrade? It's easy: just run yarn set version berry in your project, and you'll get the latest build. Want to skip the upgrade? Just revert the changes!

Linker improvementsโ€‹

Node-modules linkerโ€‹

Some people can't migrate to Plug'n'Play installs just yet. That's fine! Some of our contributors don't use it! Yarn supports node_modules installs too! And thanks to Larixer's impressive work, we're happy to report that even large and complex repositories have successfully upgraded to Yarn 2. And when I say large, I mean freaking massive ones ๐Ÿค“

In fact, our position is now that the node_modules linker in Yarn 2 is a strict improvement over the v1. Multiple hoisting issues have been identified and fixed, and the workspace support has also been improved significantly.

To give you an idea, back in the v1, Babel had never been able to use the stock Yarn workspaces. We all wanted it to happen, but because of the very tricky nature of self-hosted compiler repositories, it proved very challenging. Until now! The Babel and Jest repositories are now powered by Yarn 2, and that's frankly the best seal of quality we could hope for.

So if you're still on the fence about Plug'n'Play ... don't use it for now! Just migrate for all the other speed and stability and UX improvements ๐Ÿ˜ƒ

Loose modeโ€‹

The Plug'n'Play linker also improved, with the introduction of the Loose Mode. In Loose Mode, Yarn will simply warn should the runtime make an unsafe module access, avoiding to throw hard exceptions. This works because we generate at install-time the hoisting map that would have been generated by the node-modules linker, then we use that as a fallback pool for any unspecified dependency. It's still unsafe, but now you can quickly get a bird's eye view of all the potential problems without having to fix them all immediately.

Note that the loose mode isn't enabled by default because, somewhat ironically, it may lead to more verbose executions than the strict mode depending on various factors. In particular, packages that wrapped optional require calls between try/catch blocks won't be able to prevent the warnings from being emitted, thus causing false positive.

Major improvements to the git: protocolโ€‹

Workspace cloningโ€‹

For the past years, most projects have typically followed an "edit, commit, push, release" workflow - the first three parts happening on GitHub while the fourth one was being delegated to the npm registry. Downloading dependencies from Git was always an option, of course, but it didn't always received the attention it deserved. In particular, cloning specific packages from monorepos was still an unsolved problem.

With Yarn 2.1, this situation changes. Yarn is now able to clone any workspace from any Yarn project. Note that this only works with Yarn projects at the moment due to the lack of

yarn workspace <name> run build
counterparts on current npm and pnpm releases.

Respectful buildsโ€‹

See, there's a very important misconception that we (as in, the package manager authors, collectively speaking) have failed to address during the past years. They are not interchangeable. You cannot use X instead of Y and expect a reproducible build. Regardless of what the advertisement says, each package manager has its own feature set, and to expect them all to be in sync is fruitless. We sometimes implement features we like from other package managers, of course, but when all is said, each project still has its own characteristics that others will never truly replicate. And that's fine!

So what does that mean for Git builds in particular? Imagine, you want to use a project that's maintained by someone using pnpm. That's fair. Well, until now, if you were referencing this project with a git: dependency, Yarn would clone it, then run yarn install, then yarn pack. All good! But wait ... did it run yarn install? Why not pnpm install? Turns out, there were no good reasons. Package managers aren't interchangeable, as I was saying. If a project is configured with a pnpm-lock.yaml, then using Yarn to install it is wrong, and would lead to unpredictable builds. Clearly, that's not an acceptable behaviour.

And so we fixed it! Yarn will now properly detect which packages managers are meant to be used by projects cloned from git dependencies. If there's a yarn.lock, it'll be Yarn. If there's a pnpm-lock.yaml, it'll be pnpm. And if there's a package-lock.json, npm it is.

CLI Improvementsโ€‹

Readabilityโ€‹

The output was very verbose, sometimes hiding important information (especially on CI, where the cache is either always there or never there). Various changes were made to streamline the output and make it easier to digest.

  • On terminals, only five fetch notifications will be displayed at a time. The sixth one will cause the removal of the oldest one, and so forth.

  • On CI, Yarn will now print a one-line summary instead of the whole definition (unless configured otherwise).

  • A new optional setting, preferTruncatedLines, will ensure that infos and warnings only take a single line each, keeping your output clean and tidy.

  • Most CI systems will offer fold groups on each Yarn step. We're still tweaking a bit this behaviour, and we encourage CI maintainers to reach out to us if you wish to discuss better integrations in this area.

Focused workspacesโ€‹

The yarn workspaces focus command is a new addition inspired by a 1.x feature of the same name. It allows you to only install the dependencies from one specific workspace (plus its own workspace dependencies), thereby decreasing the install size by a significant factor. Coupled to the --production flag, it's a great tool for developers looking to integrate monorepos with Docker images.

By the way, the focus implementation takes exactly 99 lines of code. If you're curious what a plugin looks like, it's a prime example to keep in mind ๐Ÿ˜‰

Deep accesses from yarn config get/setโ€‹

The yarn config get/set commands now accept deep paths (ie foo.bar), allowing you to access settings with different levels of granularity.

Additionally, the configuration will now always be redacted before being printed (unless requested otherwise), thereby preventing secrets from accidental leaks.

Meta improvementsโ€‹

Cache filenamesโ€‹

Our cache filenames used to be versioned using a global cache key. As a result, each time we had to bump the cache key (for example because we fixed an issue in the tarball conversion algorithm), all file names changed and were causing a fairly large noise in the Git history for people using zero-installs.

This isn't the case anymore, as we made the cache content-indexed. Each file will only ever change if the archive content actually changes! ๐Ÿ’ซ

Playgroundโ€‹

One of our contributors put CodeSandbox and Yarn together in an impressive playground. Through it, you can easily build reproduction cases for bugs you encounter, decreasing the time needed for us to understand and fix them.

Documentation indexโ€‹

Thanks to Algolia, the Yarn website is now indexed and can be searched from the status bar. We hope this will allow you to quickly find any information you're looking for - whether it's authentication configuration, gitignore examples, or lexicon entries.

VSCode Zip Filesystemโ€‹

We've published the Zip FS extension on the VSCode Marketplace. Thanks to the work from Matt Penrice, using the Jump to Definition feature with the extension installed will properly send you to the right files, opened straight from the zip archive.

Note that VSCode has an internal limitation preventing the TypeScript server to cover the files located within zip archives (ie you can Jump to Definition from your sources to zip files, but TypeScript won't show its types once you get there). Please upvote the following issue to raise the ticket's priority (we already made a PR, but it unfortunately got rejected).

Other improvementsโ€‹

Performancesโ€‹

  • The Plug'n'Play runtime has been further optimized, which may yield significant boost in some cases (in particular ESLint when using the eslint-plugin-import package).

  • The binary size also received a lot of attention, and the 2.1 Yarn binary now takes 2.35MB, vs 2.91MB for the 2.0.

###ย Ecosystem

  • Packages can now declare they need to be unpacked in order to be functional using the new "preferUnplugged": true field in the manifest. This will hurt the experience of your users (your project will require hard installs, meaning a heavier footprint and slower installs), so please refrain using this field unless there's absolutely no other choice.

What's to come?โ€‹

We'll try to make more regular minor releases from now on, shipping exactly one minor per month (eventually leading up to the release of Yarn 3 in January 2021). Some topics we have in mind for the next one (come help us! we have a lot of Good First Issues!):

  • Add a new dedupe command to optimize dependency trees
  • Add changelog support to the builtin release workflow
  • Add support for the exports field
  • Add yarn list & yarn fund
  • Add the telemetry support (RFC)
  • And more...!

Of course that's only on the top of my head, so it's possible our objectives shift during the next weeks depending on our own priorities - and of course depending on whether you help us or not ๐Ÿ˜›

Until then stay safe, wear a mask, and see you next month!