あまブログ

ドキドキ......ドキドキ2択クイ〜〜〜〜〜〜〜ズ!!

【Rails】bin/yarnを解読する

Railsアプリはデフォルトでbin配下に各種のbinstubを作成する。

bin/yarnyarnのbinstub。

bin/yarnがどうやってyarnを実行しているのか気になったので、bin/yarnのコードを読んでみた。

1. 実行環境

2. bin/yarn

自分の環境では以下のbin/yarnファイルが作成されていた。

#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
  yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
    select { |dir| File.expand_path(dir) != __dir__ }.
    product(["yarn", "yarn.cmd", "yarn.ps1"]).
    map { |dir, file| File.expand_path(file, dir) }.
    find { |file| File.executable?(file) }

  if yarn
    exec yarn, *ARGV
  else
    $stderr.puts "Yarn executable was not detected in the system."
    $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
    exit 1
  end
end

3. コードの解説

APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
  ~
end
  • Dir.chdirでブロック内の処理をAPP_ROOTで行うようにする
ENV["PATH"].split(File::PATH_SEPARATOR)
  • パスを要素に持つ配列を返す
    • ENV["PATH"]でパスの文字列を返す
    • split(File::PATH_SEPARATOR)でパスの文字列を:で分割してそれぞれのパスを要素に持つ配列を返す
select { |dir| File.expand_path(dir) != __dir__ }
  • パスの配列から__dir__(Users/hoge/myapp/bin)を除いた配列を返す
product(["yarn", "yarn.cmd", "yarn.ps1"])
  • パスの配列とファイル名の配列(["yarn", "yarn.cmd", "yarn.ps1"])の直積を返す
    • [1,2,3].product([4,5]) # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
map { |dir, file| File.expand_path(file, dir) }
  • 各組み合わせのフルパスを作成する
    • ["/usr/local/bin", "yarn"]だったら、"/usr/local/bin/yarn"にする
find { |file| File.executable?(file) }
  • 最初に見つかった実行可能なyarnファイルを返す→"/usr/local/bin/yarn"
exec yarn, *ARGV
  • execでyarnコマンドを実行する
    • bin/yarnならyarn(yarn installエイリアス)が実行されるし、bin/yarn lintならyarn lint(yarn run lintエイリアス)が実行される

【参考】