- installing packages wasn’t fast/consistent enough, and
- there were security concerns, as npm allows packages to run code on installation.
But, don’t be alarmed! This is not an attempt to replace npm completely. Yarn is only a new CLI client that fetches modules from the npm registry. Nothing about the registry itself will change — you’ll still be able to fetch and publish packages as normal.
Should everyone jump aboard the Yarn hype train now? Chances are you never encountered these problems with npm. In this article, we’re going to compare npm and Yarn, so you can decide which is best for you.
Yarn vs npm: Functional Differences
At a first glance Yarn and npm appear similar. As we peek under the hood though, we realize what makes Yarn different.
The yarn.lock File
package.json, the file where both npm as Yarn keep track of the project’s dependencies, version numbers aren’t always exact. Instead, you can define a range of versions. This way you can choose a specific major and minor version of a package, but allow npm to install the latest patch that might fix some bugs.
In an ideal world of semantic versioning, patched releases won’t include any breaking changes. This, unfortunately, is not always true. The strategy employed by npm may result into two machines with the same
package.json file, having different versions of a package installed, possibly introducing bugs.
To avoid package version mis-matches, an exact installed version is pinned down in a lock file. Every time a module is added, Yarn creates (or updates) a
yarn.lock file. This way you can guarantee another machine installs the exact same package, while still having a range of allowed versions defined in
In npm, the
npm shrinkwrap command generates a lock file as well, and
npm install reads that file before reading
package.json, much like how Yarn reads
yarn.lock first. The difference here is that Yarn always updates
yarn.lock automatically, where npm requires you to maintain it.
Whenever npm or Yarn needs to install a package, it carries out a series of tasks. In npm, these tasks are executed per package and sequentially, meaning it will wait for a package to be fully installed before moving on to the next. Yarn executes these tasks in parallel, increasing performance.
For comparison, I installed the express package using both npm and Yarn without a shrinkwrap/lock file and with a clean cache. This installs 42 packages in total.
- npm: 9 seconds
- Yarn: 1.37 seconds
I couldn’t believe my eyes. Repeating the steps yielded similar results. I then installed the gulp package, resulting in 195 dependencies.
- npm: 11 seconds
- Yarn: 7.81 seconds
It seems the difference closely depends on the amount of packages that are being installed. Either way, Yarn is consistently faster.
By default npm is very verbose. For example, it recursively lists all installed packages when running
npm install <package>. Yarn on the other hand, isn’t verbose at all. When details can be obtained via other commands, it lists significantly less information with appropriate emojis (unless you’re on Windows).
Yarn vs npm: CLI Differences
Other than some functional differences, Yarn also has different commands. Some npm commands were removed, others modified and a couple of interesting commands were added.
Unlike npm, where global operations are performed using the
--global flag, Yarn commands need to be prefixed with
global. Just like npm, project-specific dependencies shouldn’t need to be installed globally.
global prefix only works for
yarn ls and
yarn remove. With the exception of
yarn add, these commands are identical to their npm equivalent.
npm install command will install dependencies from the
package.json file and allows you to add new packages.
yarn install only installs the dependencies listed in
package.json, in that order.
npm install <package>,
yarn add <package> allows you to add and install a dependency. As the name of the command implies, it adds a dependency, meaning it automatically saves a reference to the package in the
package.json file, just as npm’s
--save flag does. Yarn’s
--dev flag adds the package as a developer dependency, like npm’s
yarn licenses [ls|generate-disclaimer]
At the time of writing, no npm equivalent is available.
yarn licenses ls lists the licenses of all installed packages.
yarn licenses generate-disclaimer generates a disclaimer containing the contents of all licenses of all packages. Some licenses state that you must include the project’s license in your project, making this a rather useful tool to do that.
This command peeks into the dependency graph and figures out why given package is installed in your project. Perhaps you explicitly added it, perhaps it’s a dependency of a package you installed.
yarn why helps you figure that out.
This command upgrades packages to the latest version conforming to the version rules set in
package.json, instead of the exact versions defined in
yarn.lock. To achieve the same with npm, you would run:
rm -rf node_modules npm install
This command should not be confused with
npm update, which updates packages to their latest version.
yarn generate-lock-entry command generates a
yarn.lock file based on the dependencies set in
package.json. This is similar to
npm shrinkwrap. This command should be used with caution, as the lock file is generated and updated automatically when adding and upgrading dependencies via
yarn add and
Stability and Reliability
Could the Yarn hype train become derailed? It did receive a lot of issue reports the first day it was released into the public, but the rate of resolved issues is also astounding. Both indicate that the community is working hard to find and remove bugs. Looking at the number and type of issues, Yarn appears stable for most users, but might not yet be suitable for edge cases.
Note that although a package manager is probably vital for your project, it is just a package manager. If something goes wrong, reinstaling packages shouldn’t be difficult, and nor is reverting back to npm.
Perhaps you’re aware of the history between Node.js and io.js. To recap: io.js was a fork of Node.js, created by some core contributors after some disagreement over the project’s governance. Instead, io.js chose an open governance. In less than a year, both teams came to an agreement, io.js was merged back into Node.js, and the former was discontinued. Regardless of the rights or wrongs, this introduced a lot of great features into Node.js.
I’m seeing similar patterns with npm and Yarn. Although Yarn isn’t a fork, it improves several flaws npm has. Wouldn’t it be cool if npm learned from this and asked Facebook, Google and the other Yarn contributors to help improve npm instead? Although it is way too early to say if this will happen, I hope it will.
Either way, Yarn’s future looks bright. The community appears excited and is receiving this new package manager well. Unfortunately, no road map is available, so I am not sure what surprises Yarn has in store for us.
Yarn scores points with way better defaults compared to npm. We get a lockfile for free, installing packages is blazing fast and they are automatically stored in
package.json. The impact of installing and using Yarn is also minimal. You can try it on just one project, and see if it works for you or not. This makes Yarn a perfect drop-in substitute for npm.
I would definitely recommend trying Yarn on a single project sooner or later. If you are cautious about installing and using new software, give it a couple of months. After all, npm is battle-tested, and that is definitely worth something in the world of software development.
If you happen to find yourself waiting for npm to finish installing packages, that might be the perfect moment to read the migration guide 😉
What do you think? Are you using Yarn already? Are you willing to give it a try? Or is this just contributing to the further fragmentation of an already fragmented ecosystem? Let me know in the comments below.