Brought to you by our partners at Blazing Edge.
Remember the dark age of packages in web development? Searching all over the web to try and find a version of a package from some global CDN just to cut your load times by a small margin?
Well, since then, we’ve come a long way. Most libraries and packages you use for development are open sourced and hosted on Github today. Awesome tools, like Bower, have paved the way for npm, which is now the de facto standard for JS package management.
Creating an application without the massive package repository that npm has to offer is hard and simply terrifying to even imagine. It's super easy, just type
npm install mypackage and it's installed and ready to use, add
--save and it's added to the package.json. What's not to like?
Don’t get me wrong, npm is not without its imperfections. Npm is very complex and with this ever-increasing complexity, some imperfections became more apparent. Enter: Yarn.
Last week, Google, Tilde, Facebook, and Exponent collaboratively launched Yarn, a new package manager to address some of the glaring issues with npm. In this post I will take a closer look at Yarn and discuss the most important improvements that it’s claiming to make.
Simply put, to install packages using npm, you need to be connected to the internet in order to fetch the desired packages.
Alternatively, Yarn gives you the power to work in offline mode. Yarn essentially caches all packages globally that you install. If you are installing a package that you have installed previously, you don't need an internet connection at all. Offline mode also speeds up all subsequent installations of the same package since there is no need to go and fetch if from the internet.
I can’t tell you how many times different package versions installed across the team had been the culprit for a bug. Checking dependency versions tends to be an annoying starting point for every developer when trying to figure out some strange bug that only affected certain people or certain environments.
To address this, npm introduced shrinkwrap, which lets you to lock package versions for production. If you run
npm shrinkwrap it will generate a npm-shrinkwrap.json file with listed locked dependencies. However, shrinkwrap requires you to actually run it manually. If you add a new package and forget to run shrinkwrap, that package is left out.
To solve this problem, Yarn took a proven concept from other package managers - lock file. During the installation,
yarn.lock file is generated automatically. It's similar to Gemfile.lock file that Ruby on Rails developers should be very familiar with. This file locks all the versions installed, and each time Yarn installs, it will use these locked versions. If you keep this file in the repository (which you should), it guarantees that all developers, and even deploy builds, are running the same dependency versions.
The npm client uses a non-deterministic approach when installing packages. This means that the node_modules/ directory structure can vary between different systems and different developers. A common problem with this structure variance between different systems and developers is it’s a potential source for those ‘It works on my machine’ bugs.
Yarn lockfile guarantees that no matter how many times you run it on the same repository, you will always get the same results - this works across different machines and production builds. No more need for pushing node_modules to the repository or keeping it zipped somewhere so that different machines can unpack and have the exact same version of node_modules.
Determinism is an incredibly important feature for a package manager and is really long overdue with npm.
Yarn claims to be giving a big increase in dependency installation speed. I ran a few experiments to test this claim.
Using the same hardware, I picked three different repositories to compare:
- A React repository
- An internal front-end React application
- An API written in Node.js.
For each repository, I did three sets of measurements:
- one with npm3
- one with Yarn without cache
- one with Yarn when packages are already cached.
I ran multiple experiments for each and used the average. There was no significant difference when running npm3 with or without cache, so the time wasn’t noted.
As you can see, Yarn is about twice as fast as npm3 on the initial installation. On the second run, when packages are cached, and don’t need to be fetched over the network, Yarn is an impressive five times faster than npm3 installations. Needless to say, the increase is pretty apparent.
For the past week or so I have been playing with Yarn, and it definitely seems more reliable than the current version of npm. I’m excited to see how npm, as the current king of JS package managers, will react to this. Yarn clearly improves on a few aspects and I expect to see npm introducing at least some of these improvements.
In the meantime, ECP will probably make a switch from npm to Yarn because the benefits seem to be so evident and clear.