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側のオプションをいじることで効果出そうな気がするが試す気力がなくなってしまったためこれで終了
とりあえず快適!