A couple of days ago Facebook released Yarn, a new package manager for Javascript, with a focus on speed and consistent package dependency management across machines.

With Yarn, engineers still have access to the npm registry, so I thought it worth the try to test the claimed speed improvements between package installation using yarn and npm default installation process.

For my tests I used ng-lightninga project for native Angular 2 components & directives for Lightning Design System I use lately for a project. Kudos to my friend tbekos, the main contributor of the project for his awesome work.

Project dependencies

Ng-lightning has the following dependencies

  "name": "ng-lightning",
  "version": "0.27.1-0",
  "description": "Native Angular 2 components and directives for Lightning Design System",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ng-lightning/ng-lightning.git"
  "bugs": {
    "url": "https://github.com/ng-lightning/ng-lightning/issues"
  "main": "bundles/ng-lightning.umd.js",
  "module": "ng-lightning.js",
  "typings": "ng-lightning.d.ts",
  "scripts": {
    "test": "gulp test",
    "tdd": "gulp tdd",
    "lint": "gulp lint:ts --failOnError=true",
    "build": "gulp",
    "start": "npm run build && gulp build:watch",
    "demo": "webpack --config ./demo/webpack.config.js --watch",
    "demo:build": "npm run build && webpack --config ./demo/webpack.config.js",
    "demo:release": "npm run demo:build && node scripts/gh-pages",
    "prerelease": "npm run build && npm test",
    "release": "node scripts/release"
  "keywords": [
    "lightning design system",
  "author": "Tasos Bekos <tbekos@gmail.com>",
  "license": "MIT",
  "peerDependencies": {
    "@angular/common": "^2.0.0",
    "@angular/core": "^2.0.0",
    "@angular/forms": "^2.0.0",
    "@salesforce-ux/design-system": "^2.0.1"
  "dependencies": {
    "tether": "^1.2.0"
  "devDependencies": {
    "@angular/common": "^2.1.2",
    "@angular/compiler": "^2.1.2",
    "@angular/compiler-cli": "^2.1.2",
    "@angular/core": "^2.1.2",
    "@angular/forms": "^2.1.2",
    "@angular/http": "^2.1.2",
    "@angular/platform-browser": "^2.1.2",
    "@angular/platform-browser-dynamic": "^2.1.2",
    "@angular/platform-server": "^2.1.2",
    "@angular/router": "^3.1.2",
    "@salesforce-ux/design-system": "^2.1.3",
    "@types/core-js": "^0.9.34",
    "@types/jasmine": "^2.5.36",
    "@types/node": "^6.0.46",
    "@types/tether": "^1.1.27",
    "app-root-path": "^2.0.1",
    "browser-sync": "^2.17.5",
    "browser-sync-webpack-plugin": "^1.1.3",
    "clean-webpack-plugin": "^0.1.13",
    "conventional-changelog-cli": "^1.2.0",
    "copy-webpack-plugin": "^4.0.0",
    "core-js": "^2.4.1",
    "dateformat": "^1.0.12",
    "del": "^2.2.2",
    "gh-pages": "^0.11.0",
    "glob": "^7.1.1",
    "gulp": "gulpjs/gulp#4.0",
    "gulp-cached": "^1.1.0",
    "gulp-inline-ng2-template": "^3.0.2",
    "gulp-tslint": "^6.1.2",
    "gulp-typescript": "^3.1.1",
    "html-loader": "^0.4.4",
    "html-webpack-plugin": "^2.24.0",
    "inquirer": "^1.2.2",
    "jade": "^1.11.0",
    "jade-loader": "^0.8.0",
    "jasmine-core": "^2.5.1",
    "jasmine-spec-reporter": "^2.7.0",
    "json-loader": "^0.5.3",
    "karma": "^1.3.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-coverage": "^1.1.1",
    "karma-firefox-launcher": "^1.0.0",
    "karma-ie-launcher": "^1.0.0",
    "karma-jasmine": "^1.0.2",
    "karma-safari-launcher": "^1.0.0",
    "karma-sauce-launcher": "^1.1.0",
    "karma-sourcemap-loader": "^0.3.6",
    "lazypipe": "^1.0.1",
    "markdown-loader": "^0.1.7",
    "prismjs": "^1.5.1",
    "prismjs-loader": "0.0.4",
    "q": "^1.4.1",
    "raw-loader": "^0.5.1",
    "replace": "^0.3.0",
    "request": "^2.76.0",
    "rxjs": "5.0.0-beta.12",
    "semver": "^5.3.0",
    "shelljs": "^0.7.5",
    "simple-git": "^1.57.0",
    "systemjs": "^0.19.40",
    "systemjs-builder": "^0.15.33",
    "tether": "^1.3.7",
    "ts-loader": "^0.9.5",
    "tslint": "^3.15.1",
    "typescript": "^2.0.6",
    "webpack": "^1.13.3",
    "yargs": "^6.3.0",
    "zone.js": "^0.6.26"

which results in a 153 MB node_modules folder with 49.452 files and 4.103 folders.


Using NPM (3.10.3)

To measure the time it takes for the installation process to complete I use the measure-command cmdlet, in powershell, which enables you to measure the running time of a command or script down to the millisecond.

After cloning the project, I start the package installation using `npm install`.

> git clone https://github.com/ng-lightning/ng-lightning.git
> cd ng-lightning
> measure-command {npm i} | select @{n="time";e={$_.Minutes,"Minutes",$_.Seconds,"Seconds",$_.Milliseconds,"Milliseconds" -join " "}}

The package installation completed in 2 minutes 13 seconds 768 ms (00:02:13.768).

Using Yarn (0.16.1, no lock file)

We followed the same steps as before, and use the built-in timer yarn has.

The first time yarn install is executed, a lock file is generated in order to resolve issues around versioning and non-determinism.  These lockfiles lock the installed dependencies to a specific version, and ensure that every install results in the exact same file structure in node_modulesacross all machines. The written lockfile uses a concise format with ordered keys to ensure that changes are minimal and review is simple.

> git clone https://github.com/ng-lightning/ng-lightning.git
> cd ng-lightning
> yarn instal

The package installation completed in 1 minute 46 seconds and 120 ms (00:01:46.120).

Using Yarn (with lock file)

I deleted the node_modules folder and executed again the yarn install command. Due to the lock file generated from the previous installation, I was expecting to see an even faster package installation.

The package installation completed in 1 minute 37 seconds and 140ms (00:01:37.140).


Package installation using yarn is about 25% faster, compared to npm install, the first time you use it, where no lock files are created, and about 37% faster after the lock files are created.

Categorized in: