Rails5 + Angular6で開発していてwebpackerを使わずにCapistranoを使ってAngularのビルドコマンドを直に実行していました
.....が、待てどくらせどAngularのビルドが終わらない!
大体10分くらい待たされているよう
これではデプロイどころではないので調べました
前提
プロジェクトの構成としてRailsのルートディレクトリにfrontendディレクトリがあってそこにAngularのファイル郡があります
デプロイはCapistranoを使っているのでfrontendへ移動してビルドコマンドを叩くという感じです
コマンドのー部を抜粋します
- lib/capistrano/tasks/angular.rake
namespace :angular do
task :modules_install do
run_locally do
execute("cd frontend && npm install")
end
end
task :build do
run_locally do
execute("cd frontend && npx ng build --prod --aot")
end
end
task :s3put do
run_locally do
execute("aws s3 cp frontend/dist/project s3://prject-root --recursive")
end
end
end
- modules_install
- build
- s3put
の順で実行されていきます
切り分けを行うために1つづつコマンドを実行していくとボトルネックはbuildであるという事がわかりました
そしてプロセスを見るとビルドのコマンド自体は終わっているのに次のtaskへ進まない。。。
buildの中で何をしているのかpryを入れて見てみたところ
怪しそうな箇所を見つけました
/home/vagrant/.anyenv/envs/rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/local.rb def execute_command(cmd)
41: def execute_command(cmd)
=> 42: output.log_command_start(cmd)
43:
44: cmd.started = Time.now
45:
46: Open3.popen3(cmd.to_command) do |stdin, stdout, stderr, wait_thr|
47: stdout_thread = Thread.new do
48: while (line = stdout.gets) do
49: cmd.on_stdout(stdin, line)
50: output.log_command_data(cmd, :stdout, line)
51: end
52: end
53:
54: stderr_thread = Thread.new do
55: while (line = stderr.gets) do
56: cmd.on_stderr(stdin, line)
57: output.log_command_data(cmd, :stderr, line)
58: end
59: end
60:
61: stdout_thread.join
62: stderr_thread.join
63:
64: cmd.exit_status = wait_thr.value.to_i
65:
66: output.log_command_exit(cmd)
67: end
68: end
..... ..... .....
From: /home/vagrant/.anyenv/envs/rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/airbrussh-1.3.0/lib/airbrussh/delegating_formatter.rb @ line 24:
Owner: Airbrussh::DelegatingFormatter
Visibility: public
Number of lines: 3
define_method(method) do |*args|
formatters.map { |f| f.public_send(method, *args) }.last
end
[6] pry(#<SSHKit::Formatter::Airbrussh>)> method
=> "log_command_start"
..... ..... .....
From: /home/vagrant/.anyenv/envs/rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/formatters/pretty.rb @ line 19 SSHKit::Formatter::Pretty#log_command_start:
18: def log_command_start(command)
=> 19: host_prefix = command.host.user ? "as #{colorize(command.host.user, :blue)}@" : 'on '
20: message = "Running #{colorize(command, :yellow, :bold)} #{host_prefix}#{colorize(command.host, :blue)}"
21: write_message(command.verbosity, message, command.uuid)
22: write_message(Logger::DEBUG, "Command: #{colorize(command.to_command, :blue)}", command.uuid)
23: end
ここまで追ったのですが見失ってしまいました
From: /home/vagrant/.anyenv/envs/rbenv/versions/2.5.1/lib/ruby/2.5.0/forwardable.rb @ line 223 SSHKit::Formatter::Abstract#colorize:
220: def #{ali}(*args, &block)
221: #{pre}
222: begin
=> 223: #{accessor}
224: end#{method_call}#{FILTER_EXCEPTION}
ココらへんでどういう動きをしているのかがわからなくなってしまいました
cmd
=> #<SSHKit::Command:0x00007f7f3150b498
@args=[],
@command="cd frontend && npx ng build --prod --aot",
@full_stderr="",
@full_stdout="",
@options=
{:raise_on_non_zero_exit=>true,
:run_in_background=>false,
:in=>nil,
:env=>nil,
:host=>#<SSHKit::Host:0x00007f7f2e166368 @hostname="localhost", @keys=[], @local=true, @user="vagrant">,
:user=>nil,
:group=>nil},
@stderr="",
@stdout="">
output SSHKit::Formatter::Airbrussh ..... ..... .....
正直途中で見失ったのですがどうもoutputが実行しているlog_command_strtコマンドが怪しいというところまでは追えました
なのでoutputに何が使われているのか見てみたところAirbrusshというのが出てきたので何か見てみるとログのフォーマッタツールのようです
フォーマッタだし関係ないかーなんて思っていたのであまり疑ってなかったのですが試しにフォーマッタをprettyに変えたところとくに待たされることがなくなりました
とういことで詳細まで終えていないもののAirbrusshで`Angularのビルド時の出力をフォーマットする処理がうまく行ってない様です
angular/cliでbuild以外のコマンドを実行したときは問題ないことを確認したので
build時の挙動にも相性的な問題がありそう
デフォルトだとangular-cliでbuildすると進捗表示が出てくるのでそれをなくしてみます
--no-progressオプションをつけてビルドすると待たされることがなくなった

この進捗表示が良くないらしい
なのでワークアラウンドではあるのですが解決策として2つ挙げられることがわかりました
- capistranoのフォーマッタ設定を変える
set :format, :pretty
- Angularのビルド時に進捗表示を出さない
--no-progress
これでデプロイ時のAngularのビルドに待たされることがなくなりました
これ以外にもcapistrano側のオプションをいじることで効果出そうな気がするが試す気力がなくなってしまったためこれで終了
とりあえず快適!