Why We Use Yarn

Much like operating systems, JavaScript package managers tend to be a source of much debate. One developer will swear by their package manager while another vows never to use it. Some developers simply don’t care, and new developers often find themselves struggling to answer the question of which package manager to use.

Before you get your hopes up, let me warn you that I’m not going to attempt to convince you what the “right” package manager is. They all have their benefits! npm is the officially supported, tried-and-true package manager. Yarn focuses on developer experience and pioneering new approaches to package management. npm has excellent performance and helps enforce best practices for package access. The best package manager for you is not what this blog or that blog recommends, but the one you feel most comfortable with. This post is intended to share why we at Acquia chose Yarn as our package manager.

Developer experience

Yarn puts a big focus on developer experience, making the mundane tasks a little bit easier to do. From the outside, this can seem insignificant, but the long-term savings are worth it.

Easily run scripts and binaries.

The yarn run command allows running both scripts (e.g., lint) and binaries (e.g., webpack) for a consistent experience. Also, the run keyword is optional, allowing you to simplify commands even further.

# npm
npm run lint
npx webpack

# Yarn
yarn lint
yarn webpack

Automatic argument forwarding

When running scripts or binaries, Yarn will automatically forward arguments to the underlying script/binary. No need to add -- to your commands.

# npm
npm run lint -- --fix

# Yarn
yarn lint --fix

CLI output

Yarn’s output is very easy to follow and understand thanks to logical groupings of operations, progress bars, and colorized output. Additionally, they provide useful error codes (e.g., YN0060) in each line of the output, which you can look up in Yarn’s extensive error codes documentation.

Project-level versioning

Yarn uses project-level versioning where the Yarn binary is committed to your repository, which allows different projects to use different Yarn versions. This is extremely beneficial as it allows you to update projects separately without needing to coordinate with multiple teams to update all their projects at the same time.

With the addition of Corepack into Node.js, project-level versioning will be available for npm and pnpm, but that will take some time to become generally available.


Yarn supports plugins to extend and customize the functionality of Yarn. This allows you as a community member to build features that may not be included in the core of Yarn to meet your specific package management needs.

Check out the Yarn plugin docs for a list of community plugins that have been built, including the outdated plugin that I built and maintain.


Yarn includes an impressive list of protocols that can be used for resolving dependencies. While you’ve likely seen the most popular ones, including semver (e.g., ^1.0.0), tags (e.g., latest), and git (e.g., [email protected]:Widen/foo.git), Yarn supports a number of other protocols. Three of my favorites are:

  • patch: - The patch protocol allows you to reference a package along with a patch file that can be used to patch bugs in the given package. This is very useful when contributing a bug fix to an open source project where you need to use the fixed version immediately.
  • portal: - The portal protocol creates a link to another folder on your computer which allows you to test changes you are making to a package without having to publish a pre-release. This protocol is very easy to use thanks to the yarn link CLI command.
  • workspace: - The workspace protocol creates a link to a package in another workspace which ensures that you will never accidentally download an old version of a workspace from the registry. This protocol is great for multi-package monorepos.

Miscellaneous niceties

Yarn has plenty more nice features to talk about, including their flagship feature Plug’n’Play, but here are a few other small niceties that we enjoy using.

  • Workspace constraints - Constraints are a very powerful way of ensuring consistency between packages in a monorepo. We use constraints extensively in our component and utility libraries.
  • yarn up wildcarding - The yarn up command supports wildcards to upgrade groups of dependencies (e.g., yarn up '@babel/*').

Downsides of Yarn

While Yarn does have a lot of benefits like I just described, it comes with its share of downsides. I’m not going to cover these in great detail for the sake of time, but I wanted to at least mention them.

  • Non-standard - New users can’t just run yarn in a fresh install of Node. Somewhat ironically, Yarn is installed via npm!
  • Configuration files - Yarn has plenty. Setting up a new project requires configuration in four or five places in most cases.
  • Plugin development woes - Writing Yarn plugins to provide missing features is no picnic. Trust me, I’ve done it.