LoginSignup
215
165

More than 5 years have passed since last update.

yarnがnpmと何が違うのか試してみた

Last updated at Posted at 2016-10-12

はじめに

こんなpackage.jsonがあるとして

$ cat package.json
{
  "name": "sample",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "gulp-cache": "^0.4.5",
    "gulp-debug": "^2.1.2",
    "gulp-eslint": "^3.0.1",
    "gulp-size": "^2.1.0"
  }
}

yarnpackage.jsonに対応しているため、
npm install同様(デフォルトでは)node_modulesにモジュールが降ってきます。

# npm の場合
$ npm install

# yarn の場合
$ yarn
# または
$ yarn install

ちなみに上記のpackage.jsonは、以下のコマンドで、作成からモジュールのインストールまで行えます。

# package.json の作成
$ yarn init
# パッケージの追加すると、同時に取得される
$ yarn add gulp-cache gulp-debug gulp-eslint gulp-size
yarn add v0.15.1
[1/4] Resolving packages...

npm installと何が違うの?

yarn.lock なるファイルが作成されます。

yarnの場合yarn.lockが生成されます。

これはnpmの shrinkwrap に相当する機能で、
これにより依存するモジュールのバージョンを固定することができます。

# 中身はこんな感じ
$ head yarn.lock
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
acorn-jsx@^3.0.0:
  version "3.0.1"
  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
  dependencies:
    acorn "^3.0.4"

acorn@^3.0.4:
  version "3.3.0"

じゃあ shrinkwrap との違いは何かといえば

  • デフォルトで生成されるので簡単に利用できる
  • 各モジュールがソートされており構成管理が容易

確かに人が見てもnpm-shrinkwrap.jsonと比べて記載が非常に分かりやすいです。

Yarn: A new package manager for JavaScript

モジュールのフォルダ構造が変わります。(追記あり)

node_modulesの中身を見れば一目瞭然

# npm(v2) の場合
$ ls node_modules/
gulp-cache/  gulp-debug/  gulp-eslint/  gulp-size/

# yarn の場合
$ ls node_modules/
acorn/                 generate-object-property/  normalize-package-data/
acorn-jsx/             get-stdin/                 number-is-nan/
ajv/                   glob/                      object.omit/
ajv-keywords/          globals/                   object.pick/
ansi-escapes/          globby/                    object-assign/
ansi-regex/            glogg/                     once/
..... 略

yarnは依存モジュールも含めてnode_modules直下に入るためフォルダの数が多くなります。
でもファイルサイズはyarnの方が小さいです。

# npm(v2) の場合
$ du -sh node_modules/
32M     node_modules/

# yarn の場合
$ du -sh node_modules/
20M     node_modules/

これは依存により重複しているモジュール、
例えばreadable-streamの場合だと、以下のように配置されていました。

# npm(v2) の場合
$ find -type d | grep -e readable-stream$
./node_modules/gulp-cache/node_modules/gulp-util/node_modules/multipipe/node_modules/duplexer2/node_modules/readable-stream
./node_modules/gulp-cache/node_modules/gulp-util/node_modules/through2/node_modules/readable-stream
./node_modules/gulp-cache/node_modules/readable-stream
./node_modules/gulp-debug/node_modules/gulp-util/node_modules/multipipe/node_modules/duplexer2/node_modules/readable-stream
./node_modules/gulp-debug/node_modules/through2/node_modules/readable-stream
./node_modules/gulp-eslint/node_modules/bufferstreams/node_modules/readable-stream
./node_modules/gulp-eslint/node_modules/eslint/node_modules/concat-stream/node_modules/readable-stream
./node_modules/gulp-eslint/node_modules/gulp-util/node_modules/multipipe/node_modules/duplexer2/node_modules/readable-stream
./node_modules/gulp-eslint/node_modules/gulp-util/node_modules/through2/node_modules/readable-stream
./node_modules/gulp-size/node_modules/gulp-util/node_modules/multipipe/node_modules/duplexer2/node_modules/readable-stream
./node_modules/gulp-size/node_modules/through2/node_modules/readable-stream

# yarn の場合
$ find -type d | grep -e readable-stream$
./node_modules/concat-stream/node_modules/readable-stream
./node_modules/duplexer2/node_modules/readable-stream
./node_modules/readable-stream
./node_modules/through2/node_modules/readable-stream

npmで重複されていたモジュールがyarnではきれいに整理されています。
ちなみにそれぞれ以下のバージョンのモジュールがインストールされてました。

module version
./node_modules/concat-stream/node_modules/readable-stream 2.0.6
./node_modules/duplexer2/node_modules/readable-stream 1.1.14
./node_modules/readable-stream 2.1.5
./node_modules/through2/node_modules/readable-stream 2.0.6

この中で最新の(v2.1.5)だけを利用しても問題なさそうな場合は--flatをつけて実行します。
すると以下のようにどのバージョンのモジュールを使用するかを選択できます。

$ yarn --flat
info Unable to find a suitable version for "readable-stream", please choose one by typing one of the numbers below:
  1) "readable-stream@^2.0.4, readable-stream@^2.0.2" which resolved to "2.1.5"
  2) "readable-stream@~2.0.0" which resolved to "2.0.6"
  3) "readable-stream@~1.1.9" which resolved to "1.1.14"
Answer?:

選択したバージョンがpackage.jsonresolutionsとして勝手に記録されました。

$ cat package.json
{
  "name": "sample",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "gulp-cache": "^0.4.5",
    "gulp-debug": "^2.1.2",
    "gulp-eslint": "^3.0.1",
    "gulp-size": "^2.1.0"
  },
  "resolutions": {
    "object-assign": "4.1.0",
    "readable-stream": "2.1.5",
    "vinyl": "1.2.0",
    "minimist": "1.2.0",
    "strip-bom": "3.0.0",
    "estraverse": "4.2.0",
    "acorn": "4.0.3"
  }
}
# この package.json の状態でインストール
$ yarn

これにより構造はさらにシンプル(1階層のみ)になり、フォルダサイズもちょっと小さくなりました。

$ find -type d | grep -e readable-stream$
./node_modules/readable-stream

$ du -sh node_modules/
19M     node_modules/

ただしこの場合、
バージョン指定と異なるモジュールの影響で正しく動作しない可能性があるので注意。


追記
フォルダ構成の違いは、利用しているnpmのバージョンがv2であることが原因でした。
v3を利用した場合は yarnとほぼ同じフォルダ構成が得られました。

$ npm -v
3.10.9
$ npm install
$ find -type d | grep -e readable-stream$
./node_modules/concat-stream/node_modules/readable-stream
./node_modules/duplexer2/node_modules/readable-stream
./node_modules/readable-stream
./node_modules/through2/node_modules/readable-stream

このあたり、リンク先の説明が非常に分かりやすかったです。
npm v3 Dependency Resolution

ただ私の環境ではフォルダ構成は完全に一致せず、
一部のモジュールで違いがあり、やはりyarnのほうが若干シンプルな構造になっているようでした。

# npm(v3.10.3)の場合
$ npm cache clean
$ npm install
$ find -type d | grep -e /isarray$
./node_modules/concat-stream/node_modules/isarray
./node_modules/doctrine/node_modules/isarray
./node_modules/isarray
./node_modules/isobject/node_modules/isarray
./node_modules/readable-stream/node_modules/isarray
./node_modules/through2/node_modules/isarray
$ du -sh node_modules/
21M     node_modules/

# yarn(v0.15.1)の場合
$ yarn -v
$ yarn cache clean
$ yarn install
# やはり yarn のほうがよりシンプルな構造になっている
$ find -type d | grep -e /isarray$
./node_modules/duplexer2/node_modules/isarray
./node_modules/isarray
$ du -sh node_modules/
20M     node_modules/

コメントの指摘を受け、追記させてもらいました。


まとめ

結局使えるのか?

自分のプロジェクトに適用した場合、npmに比べてモジュールのインストールがかなり早かったです。
node_modulesのファイルサイズも小さくなってまして、いつでもnpmに戻れるのでとりあえず使ってみようかなと。

方式 サイズ
npm install(v2) 378M
npm install(v3) 248M
yarn install 237M
yarn install --flat 170M

そもそも利用モジュールを減らしたい...

上記の違い以外にも、オフラインモードやネットワークのパフォーマンス改善など、
そのあたり詳しくはやっぱり公式サイトをどうぞ。

215
165
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
215
165