Michaël Perrin

Sustainable web development.

Yarn, the next package manager for JavaScript

I currently use npm for managing front lib dependencies on my projects. I was previously using Bower, which turned out to be useless and Yarn will probably be the next tool I’m going to use. Here are the main reasons:

It’s easy

Yarn uses exactly the same package.json file as npm, making it very easy to make the switch.
The dependencies are by default saved in the same node_modules directory. I didn't find any incompatibility, especially since Yarn 0.16 that supports post install scripts.

The only thing to do is to install it with one or two command lines: https://yarnpkg.com/en/docs/install (spoiler: it doesn’t need npm, contrary to Bower that was a package manager that was installed with… an other package manager).

Here are a few commands to compare NPM and Yarn:

  • Init a project with a package.json file:
    • npm init (npm)
    • yarn init (Yarn)
  • Require a package:
    • npm install [package] --save (npm)
    • yarn add [package]
    • That one will be less confusing for newcomers, with the --save that could be forgotten and give the impression that "it works on my machine")
  • Install all dependencies of the project:
    • npm install
    • yarn install

Other commands are documented here.

It is reliable

When updating packages, Yarn generates a lock file that stores all the exact versions of dependencies that have been installed. You got it, just like Composer with its composer.lock file in the PHP world.

Why having 2 files when it seems like package.json is enough?

Think about a project having this dependency:

{
    dependencies: {
        package1: "1.0.0"
    }
}

And that package1 has this dependency like this (which may not be a good idea):

{
    dependencies: {
        package2: "^1.0"
    }
}

The first time you install your project, package1 will resolve the dependency of package2 to version 1.2 (which is the latest version at the moment), but a few months later, installing the project again (on the production server for instance) may install version 1.3 of the package2 dependency, which may introduce some bugs or incompatibilities (despite semantic versioning promise).

Hence the importance of a lock file, that keeps exact version numbers of the install.
The yarn.lock file therefore needs to be commited in your project repository.

It’s fast

Here are some tests with a simple React project with some usual dependencies (Babel and some loaders, Webpack, and a few libraries):

{
  "name": "simple-react-app",
  "dependencies": {
    "material-ui": "^0.15.4",
    "react": "^15.3.1",
    "react-addons-update": "^15.3.1",
    "react-dom": "^15.3.1",
    "react-tap-event-plugin": "^1.0.0"
  },
  "devDependencies": {
    "babel-core": "^6.9.1",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "react-hot-loader": "^3.0.0-beta.3",
    "webpack": "^1.13.1",
    "webpack-dev-server": "^1.14.1"
  }
}
First run on fresh install Second run on a fresh install (with `yarn.lock` file)
NPM install 64 seconds 58 seconds
Yarn install 75 seconds 12 seconds

This is tested with npm 3.10.8 and Yarn 0.16.0.

And just like the Composer package manager in PHP (hey, PHP it not has-been after all!), Yarn keeps packages in cache, so that they can be installed again without needing an internet connection.

Michaël Perrin

Read more posts by this author.

comments powered by Disqus