[npm & Bower] Yarn 入門: npm との違いを探る

Yarn は、Facebook, Exponent, Google, Tilde によって開発されたパッケージマネージャ。
npm のより良いCLIクライアントという位置づけで、置き換える技術ではありません。

Ruby on Rails 5.1 も Yarn をサポートしましたので、いまこそ入門のタイミングでしょうか。
npm から乗り換える視点で、調査してみました。

Yarn の特徴

npm と比較して、主に以下のような特徴があります。

  1. インストールにキャッシュを利用するので ウルトラ速い
  2. checksums を見るので メガ安全
  3. yarn.lock でパッケージを管理するので スーパー確実

Installation

brew install できます。

% brew update
% brew install yarn
% yarn --version
0.24.6

npm については、以下のバージョンと比較します。

% npm -v
4.2.0

npm -> Yarn 乗り換え時の注意

yarn でインストールされるパッケージは、npm と同じく node_modules/ 以下に配置されます。
しかしながらファイル配置は diff -rq などで確認すると異なります。
yarnnpm を混ぜて利用しない方が良さそうです。

以下は、yarn で作成された node_modules/ がある状態で、npm list を実行した結果です。
エラーが発生しています。

% npm list --depth 0
yarn_project@1.0.0 /Users/****/projects/sandbox-yarn/yarn_project
├── node-pre-gyp@0.6.34 extraneous
├── react@15.5.4
└── webpack@2.6.0
npm ERR! extraneous: node-pre-gyp@0.6.34 /Users/****/projects/sandbox-yarn/yarn_project/node_modules/node-pre-gyp

npm -> Yarn への乗り換え時には node_modules/ を削除して作り直す と安全でしょう。

Usage: パッケージの管理

プロジェクト単位でパッケージを管理する方法を確認します。

package.json の生成

npm と同じく package.json を利用します。

npmYarn
npm inityarn init
% yarn init
yarn init v0.24.6
question name (yarn_project):
question version (1.0.0):
question description:
question entry point (index.js):
question repository url:
question author:
question license (MIT):
success Saved package.json
✨  Done in 5.34s.
package.json
{
  "name": "yarn_project",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT"
}

package.json が存在する場合は、以下でまとめてインストールできます。

npmYarn
npm installyarn install

パッケージの追加

プロジェクトに必要なパッケージを追加します。
あわせてインストールも行います。

npmYarn
npm install --save [package]yarn add [package]
% yarn add react
yarn add v0.24.6
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 17 new dependencies.
├─ asap@2.0.5
    :
└─ whatwg-fetch@2.0.3
✨  Done in 4.64s.

package.json や yarn.lock が無い場合は、自動で生成されます。

package.json
{
  "dependencies": {
    "react": "^15.5.4"
  }
}

プロジェクトの開発に必要なパッケージは、オプションを付けて実行します。

npmYarn
npm install --save-dev [package]yarn add [package] [--dev/-D]
% yarn add --dev webpack

パッケージの削除

パッケージの削除は、同じコマンドで削除できます。

npmYarn
npm uninstall --save [package]yarn remove [package]
npm uninstall --save-dev [package]yarn remove [package]
% yarn remove react
yarn remove v0.24.6
[1/2] Removing module react...
[2/2] Regenerating lockfile and installing missing dependencies...
success Uninstalled packages.
✨  Done in 3.44s.

パッケージのアップグレード

アップグレードコマンドが用意されています。

npmYarn
npm outdated [package]yarn outdated [package]
package.json を書き換えて npm update ※1yarn upgrade [package]

※1 普段は npm-check-updates を利用しています。他に方法があるかも知れません。

% yarn outdated
% yarn upgrade

パッケージの掃除

install, update などでたまったパッケージを掃除します。

npmYarn
npm pruneyarn clean
% yarn clean
yarn clean v0.24.6
[1/2] Creating ".yarnclean"...
[2/2] Cleaning modules...
info Removed 1552 files
info Saved 4.93 MB.
✨  Done in 3.15s.

Usage: scripts の実行

package.json に設定した scripts を実行できます。

npmYarn
npm run [script]yarn run [script]

DriftwoodJP/sandbox-es6 をサンプルに実行してみます。

% yarn install
yarn install v0.24.6
info No lockfile found.
[1/4] 🔍  Resolving packages...
warning serve > fs-promise@1.0.0: Use mz or fs-extra^3.0 with Promise Support
[2/4] 🚚  Fetching packages...
warning There appears to be trouble with your network connection. Retrying...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 73.37s.

lint タスクを実行してみます。

% npm run lint
> sandbox-es6@0.2.10 lint /Users/****/projects/sandbox-yarn/sandbox-es6
> eslint src/ test/
% yarn run lint
yarn run v0.24.6
$ eslint src/ test/
✨  Done in 1.15s.

問題なさそうです。

bin

package.json で管理しているパッケージのコマンドをカレントプロジェクト内で実行したい場合にも、yarn 経由で同じように利用できます。

npmYarn
npm binyarn bin
% $(npm bin)/webpack -v
2.6.0
% $(yarn bin)/webpack -v
2.6.0

追記:2018/11/06

ローカルプロジェクトのコマンドは npx 及び yarn run で実行できます。

npmYarn
npx [command]yarn run [command]
% yarn run webpack -v
yarn run v1.10.1
$ /Users/***/foo/node_modules/.bin/webpack -v
4.17.2
✨  Done in 0.47s.
% npx webpack -v
4.17.2

Usage: global インストール

yarn global コマンドを利用することで、グローバルで利用するパッケージの管理が可能です。

global install path

brew install した yarn の場合、以下のようなパスになりました。

% yarn global bin
/usr/local/Cellar/node/7.10.0/bin

パスの変更には ~/.npmrc の設定を活かせます。

~/.npmrc
prefix=/Users/****/local/lib/node_modules

shell にパスを通します。

~/.zshrc
# for npm
if [ -d $HOME/local/lib/node_modules/bin ]; then
    export PATH=$PATH:$HOME/local/lib/node_modules/bin
fi

変更後のパスはこうなりました。

% yarn global bin
/Users/****/local/lib/node_modules/bin

npm から yarn に乗り換える場合には、ディレクトリを一度削除する必要があります。

% sudo rm -rf ~/local/lib/node_modules/

パッケージの追加・削除・アップグレード

yarn global コマンドを実行します。

npmYarn
npm install --global [package]yarn global add [package]
npm uninstall --global [package]yarn global remove [package]
npm list --globalyarn global ls
npm update --globalyarn global upgrade
% yarn global add electron eslint
yarn global v0.24.6
[1/4] 🔍  Resolving packages...
warning electron > electron-download > nugget > progress-stream > through2 > xtend > object-keys@0.4.0:
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Installed "electron@1.6.8" with binaries:
      - electron
success Installed "eslint@3.19.0" with binaries:
      - eslint
✨  Done in 40.65s.
% yarn global ls
yarn global v0.24.6
warning No license field
info "electron@1.6.8" has binaries:
   - electron
info "eslint@3.19.0" has binaries:
   - eslint
✨  Done in 1.66s.
% ls ~/local/lib/node_modules/bin
electron@ eslint@

まとめ

  • Yarn は npm の wrapper
  • node_modules/ 以下を作り直して利用する

node_modules/ を作り直せば変わらず使える、というか便利になるという印象。
簡単に確認した限りでは、不具合もなさそう。
今後のプロジェクトでは、積極的に採用していくつもりです。

追記: npm v5.0

書いた数日後に npm@5 がリリースされたので補足。

補遺

npm の情報。

yarn licenses, yarn why, yarn generate-lock-entry