Gosh Yarn It

You’ll never believe it… A hot new technology has appeared on the Javascript scene.

What is yarn?

Yarn is a replacement for the npm package manager, the popular tool used to handle the ~300,000 packages in the npm registry.

While Yarn is designed completely replace the npm workflow, it works in concert with the existing package.json: adding or removing packages with Yarn will update both the package.json and yarn.lock.

The main commands you’ll need:

1
2
3
4
yarn  // same as npm install
yarn add  // same as npm i --save
yarn add --dev  // same as npm i --save-dev
yarn remove  // same as npm uninstall

Why bother to switch from tried-and-true npm?

Locking down the right versions of all your dependencies can be tricky.

For example: I accidentally upgraded react-addons-test-utils to a new version by adding it directly with yarn add react-addons-test-utils. This got the latest version of the package, which meant it no longer had the same version number as react and react-dom – we had specifically pinned those at an earlier minor version.

When I ran the tests, this error popped up: Module not found: Error: Cannot resolve module 'react-dom/lib/ReactTestUtils' in /Users/ebookstein/newrelic/browser/overview-page/node_modules/react-addons-test-utils (module was moved between versions of react-dom)

To pin react-addons-test-utils at a specific version, I added the version to the package name like this: yarn add react-addons-test-utils@15.3.0.

Of course, locking down dependencies at the right version numbers is something that npm did for us as well. Why replace it?

There are some minor benefits that came across right away from using yarn instead of npm. For one thing, I no longer have to remember --save – think of all the time you’ll save not pushing branches up to Github only to have your tests fail!

But there are some big-picture benefits too. We were using npm shrinkwrap to stabilize versions and dependencies. But shrinkwrap easily gets out of sync with package.json if you forget to run npm shrinkwrap, and when it fails, it fails silently.

If you want the full-length list of big-picture reasons that Facebook came up with, check out their blog post about yarn.

Switching to yarn: a few tricky bits

Installing yarn itself is easy.

brew install yarn

Then go to your project directory and run yarn to install all the packages and generate a yarn.lock (similar to Bundler’s Gemfile.lock for Ruby).

Migrating from npm to yarn is not totally seamless, however. For some reason, a few packages don’t transition as easily. In particular I had issues with node-sass and phantom-js. In one case, the issue was resolved by specifically adding the module with yarn (yarn add node-sass). In the case of phantom-js, though, we had to add a post-install script to our package.json that would run a phantomjs install script.

Also, if you use Jenkins or other tools that keep a saved copy of your node_modules, you might have to clear out the old node_modules and reinstall.

For Jenkins specifically, try:

  1. clearing the workspace,
  2. killing the instance of Jenkins, or
  3. add a post-build step to delete the workspace every time (which therefore runs a complete installation every time)

Fun bits

Fun fact: yarn preserves many helpful features of npm, like symlinking.

For example, if you wanted to use your personal copy of react instead of Facebook’s react (pretend!), then you could run yarn link inside of the react directory, then yarn link react in your project directory. This would then substitute a link to your personal react copy for every require(react).

Tying up loose ends

So far, it’s been fun to knit yarn into our development process! Though I’m still working through some of the knots…