君の名は・・YARN！

![npm_yarn_500.png](https://qiita-image-store.s3.amazonaws.com/0/71113/640215cd-a21f-51db-7eba-2abb494cc7bf.png)


#Yarnって何？
※もろにパロディですが、記事内容は真面目です。

みなさんはYarnをご存知でしょうか？
もしかしたらフロントエンジニアの方は最近耳にしたことがあるかもしれません。

まず「Yarnとは」でググってみてください。
すると・・

![kimijanai.png](https://qiita-image-store.s3.amazonaws.com/0/71113/c51d5d65-b432-9637-aa6c-2105996f2cea.png)


残念ながら意図しない別のYarnが出てきます:open_mouth:
(Apache Hadoopに詳しい方はこちらのYarnの方が馴染みがあるかも)

⬆️出だしの画像だけ見たら「npmと何か関係があんの？例の映画のごとく**入れ替わり**でもするんかいな？」と思うかも。

ここで言うYarnとはnpmと**互換性**のあるJavaScriptのパッケージマネージャーです。

**Yarn公式ドキュメント**
https://yarnpkg.com/

簡単に言えばnpm installをより高速に、そしてコンパクトにしたものです。

#Yarnのインストール
Yarnもnodeパッケージの1つなので、たった1行ですみます。
```$ npm i -g yarn```

#Yarnの使い方
`yarn`コマンドはイコール`npm install`となります。
[実際のyarnコマンド実行の様子]
![yarn実行.gif](https://qiita-image-store.s3.amazonaws.com/0/71113/ed2b76ed-ced8-b17d-67de-f180d2e0279a.gif)


その他のコマンドは以下に詳しく記載します。

##npm互換コマンド
npmと互換性があるので同じようにコマンドが使えます。

|npm |yarn|
|:--|:----|
|npm install	|yarn
|npm init|yarn init
|npm run \<script name\>	|yarn run \<script name\>
|npm test	|yarn test
|npm bin	|yarn bin
|npm install \<package name\>	|yarn \<package name\>
|npm install \<package name\> --save	|yarn add \<package name\>
|npm install \<package name\> --save-dev	|yarn add \<package name\> --dev
|npm install \<package name\> --global	|yarn global add \<package name\>
|npm uninstall \<package name\>	|yarn remove \<package name\>
|npm ls	|yarn ls
|npm cache clean	|yarn cache clean
|npm cache ls	|yarn cache ls
|npm outdated	|yarn outdated
|npm update --save	|yarn upgrade
|npm install \<package name\>@latest --save	|yarn add \<package name\>
|npm link	|yarn link
|npm login	|yarn login
|npm publish	|yarn publish

##Yarn独自のコマンド
npmには無いYarn独自のコマンドもあります。

**yarn licence ls**
インストール済みの各パッケージのライセンスとパッケージ詳細URLを表示します。
![yarn licence ls.png](https://qiita-image-store.s3.amazonaws.com/0/71113/a3e6f750-52e1-3918-b70a-69c14bcc54da.png)

**yarn licenses generateDisclaimer**
自動的にライセンス関連の文章(?)を作成してくれますが、使いどころがよくわかりません:sweat:

[yarn cheet sheet](https://shift.infinite.red/npm-vs-yarn-cheat-sheet-8755b092e5cc#.llzq6v5ee)によると`yarn licenses generate`コマンドになってますが、最新のyarnではコマンドエラーが発生します。

```bash
error Invalid subcommand. Try "ls, generateDisclaimer"
info Visit https://yarnpkg.com/en/docs/cli/licenses for documentation about this command.
```

`generateDisclaimer`は`generate`の代わりとなるコマンドっぽい。

**yarn why**
`yarn why (パッケージ名)`で指定したパッケージの詳細情報を表示することが出来ます。
![yarn why.png](https://qiita-image-store.s3.amazonaws.com/0/71113/7b74ce52-5841-9adf-ae57-e5ca2399dea2.png)


#Yarnのメリット
## パフォーマンス
「さあ、ニュータイプの力を見せてもらおうか」と思ってパッケージのインストール速度を試すと、
「あ、あれ・・？そこまで速くなくない？むしろ`npm　install`より遅くね？汗」って恐らくなります。

これはYarnはパッケージの依存性を解決してくれるため、インストールするパッケージ群の依存性が複雑であればあるほど時間がかかることによります。(シンプルなパッケージ群であれば速いです)

厳密に言うとYarnのパフォーマンスの真価は**キャッシュ**によって発揮されます。

### パッケージインストール速度計測
#### キャッシュ有無の比較
いくつかのpackage.jsonを用いて初回インストール(キャッシュなし)と2回目のインストール(キャッシュあり)で計測します。

[react-es6](https://github.com/klaemo/react-es6/blob/master/package.json)

|インストール条件|npm|yarn|
|:---------|:---------|:---------|
|キャッシュなし|0m42.693s|0m28.551s|
|キャッシュあり|0m35.316s|0m12.087s|

[webpack-demos](https://github.com/ruanyf/webpack-demos/blob/master/package.json)

|インストール条件|npm|yarn|
|:---------|:---------|:---------|
|キャッシュなし|0m41.397s|1m39.957s|
|キャッシュあり|0m41.320s|0m47.947s|

[angular2/quickstart](https://github.com/angular/quickstart/blob/master/package.json)

|インストール条件|npm|yarn|
|:---------|:---------|:---------|
|キャッシュなし|0m42.548s|0m25.273s|
|キャッシュあり|0m36.473s|0m12.264s|

webpack-demosはキャッシュありでもnpmより遅い結果となりましたが、全般的にキャッシュありの場合は高速だということが判明しました。


## モジュールがよりコンパクトに
Yarnはパッケージモジュールをよりコンパクトに配置します。
フォルダ数はnpmより多くなる場合がありますが、モジュールのサイズは小さくなります。

サンプルとしてこういったpackage.jsonを基にnpmとyarnでパッケージをインストールした時の比較をしてみましょう

```json
{
  "devDependencies": {
    "axios": "^0.9.1",
    "babel-eslint": "^4.1.8",
    "babel-preset-es2015": "^6.5.0",
    "babel-preset-react": "^6.5.0",
    "babelify": "^7.2.0",
    "browserify": "^13.0.0",
    "classnames": "^2.2.3",
    "eslint": "^1.10.3",
    "eslint-config-es2015-react": "^0.1.2",
    "eslint-plugin-react": "^3.16.1",
    "react": "^0.14.7",
    "react-dom": "^0.14.7",
    "react-redux": "^4.4.0",
    "redux": "^3.3.1",
    "redux-thunk": "^1.0.3",
    "underscore": "^1.8.3",
    "watchify": "^3.7.0"
  }
}
```

|項目|npm|yarn|
|:---------|:---------|:---------|
|ファイル数|25308|15579|
|ディレクトリ数|2031|2311|
|ディレクトリサイズ|138M|103M|

ファイル数とディレクトリサイズがnpmと比べて明らかに小さくなっています。
※ただしこれもインストールするパッケージの依存関係によって多少の差がありますのでご注意ください。


##その他

###オフラインでのインストール
既に以前パッケージをインストールしたことがあるのであれば、`yarn install --prefer-offline`によってサーバーにリクエストせずにオフラインで高速にインストールすることが可能だそうです。


###よりセマンティックな管理
yarnでインストールした後は自動的にyarn.lockというファイルが生成されます。
このyarn.lockで依存するモジュールのバージョンを固定することが出来ますが、詳細はまた後日に追記したいと思います。


#まとめ
検証した結果、実務レベルで導入はありだと個人的に思いました。
自分のプロジェクトでは以前npm installの遅さを解決する為にpnpmを使用していましたが、pnpmは高速である代わりに不安定であり、ほとほと悩まされてきたので近い内に是非Yarnを導入したいです。