npm
YARN

Yarnやっていきはじめ

More than 1 year has passed since last update.

Yarnとは

YarnFastReliableSecure なパッケージマネジメントシステムです。
Facebook製でnpm互換があり、npmよりも高速だと話題です。
rails/webpackerなどもYarnを採用しており、これから色々な環境で使われていくのではないでしょうか。
そんなYarnを導入してみたので、その手順を書きます。

実際に速いのか

速かったです。下記が実際に現在のプロジェクトでベンチマークをとってみた結果です。
※ キャッシュと/node_modulesは削除しています。

コマンド 計測時間(5回平均)
$ time npm install 44.92s
$ time yarn install 22.10s
$ time yarn install --prefer-offline 16.81s

@pine613さんがGitHub Star上位100を対象にベンチマークを出している資料があります。依存数が多くなればなるほど、速くなり、Yarnの方が遅いパターンは存在しないとのことです。この発表を聞いて、導入してみようと思いました。

yarn VS. npm@2 VS. npm@3 // Speaker Deck

Yarnの導入

公式のInstallationに従ってインストールを進めます。Macの場合は、下記、2コマンドで済みます。

console
$ brew update
$ brew install yarn

.zshrcにPATHを追加。

.zshrc
export PATH="$PATH:`yarn global bin`"

上記でyarnコマンドが実行できるように🎉

console
$ yarn --version
0.19.1

$ yarn
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
✨  Done in 18.95s.

よく使うnpmコマンドとyarnコマンドの置き換えはこちら

npm yarn
$ npm init $ yarn init
$ npm install -S PACKAGE $ yarn add PACKAGE
$ npm install -D PACKAGE $ yarn add -D PACKAGE
$ npm uninstall PACKAGE $ yarn remove PACKAGE
$ npm install $ yarn

ちなみに$ npm pruneコマンドの代替はなく、

console
$ yarn prune

yarn prune v0.19.1
error The prune command isn't necessary. `yarn install` will prune extraneous packages.
info Visit https://yarnpkg.com/en/docs/cli/prune for documentation about this command.

とのこと。賢いですね🙆

Yarnの運用

上述の通り、npmコマンドの箇所はyarnで置き換え可能なので、プロジェクトでnpmを使っていた箇所を置き換えていきましょう。この辺はプロジェクトで利用している技術次第なので、一例として、参考にしてください。Rails + Reactで開発していて、インフラ構築にAnsible、デプロイにCapistranoを利用しています。

package.json
- "build": "npm run clean && npm run webpack",
+ "build": "yarn run clean && yarn run webpack",
Procfile
- webpack: npm run dev
+ webpack: yarn run dev
  rails: bundle exec rails server -p 3000

READMEに記述がある場合は変更しておきましょう。
続いて、デプロイ周り。

playbook.yml
- - yum: name=npm
+ - get_url: url=https://dl.yarnpkg.com/rpm/yarn.repo dest=/etc/yum.repos.d/yarn.repo
+   become: yes
+ - yum: name=yarn
Capfile
- require "capistrano/npm"
+ require "capistrano/yarn"
Gemfile
  # capistrano
  gem 'capistrano'
  gem 'capistrano-bundler'
- gem 'capistrano-npm'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
+ gem 'capistrano-yarn'
  gem 'capistrano3-puma'
config/deploy.rb
- # npm
- set :npm_flags, "--production --silent --no-progress"
- set :npm_roles, :web
- set :npm_env_variables, fetch(:npm_env_variables, {})
+ # yarn
+ set :yarn_flags, "--prefer-offline --production --no-progress"
+ set :yarn_roles, :web
+ set :yarn_env_variables, fetch(:yarn_env_variables, {})

- namespace :npm do
+ namespace :yarn do
    task :build do
-     on roles fetch(:npm_roles) do
-       within fetch(:npm_target_path, release_path) do
-         with fetch(:npm_env_variables, {}) do
-           execute :npm, "run build"
+     on roles fetch(:yarn_roles) do
+       within fetch(:yarn_target_path, release_path) do
+         with fetch(:yarn_env_variables, {}) do
+           execute :yarn, "run build"
          end
        end
      end
    end
  end

- before "npm:install", "npm:prune"
- after "npm:install", "npm:build"
+ after "yarn:install", "yarn:build"

最後にCircleCI。

circle.yml
machine:
  timezone:
    Asia/Tokyo
  environment:
    YARN_VERSION: 0.19.1
  ruby:
    version: 2.3.1
  node:
    version: 6.9.1
  post:
    - if [[ $(yarn --version 2>/dev/null) != "${YARN_VERSION}" ]]; then curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version $YARN_VERSION; fi
dependencies:
  cache_directories:
    - "~/.cache/yarn"
  override:
    - yarn install --prefer-offline
    - bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
test:
  override:
    - yarn run test
    - bundle exec rspec --color --require spec_helper spec --format progress
    - bundle exec rubocop

まとめ

上述の通り、テストやデプロイにかかる時間を短縮できるメリットがあり、簡単に置き換え可能なので、Yarnを導入してみてはいかがでしょうか。

参考

Yarn
yarn VS. npm@2 VS. npm@3 // Speaker Deck
amakanでyarnを使うようにした - ✘╹◡╹✘