2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Herokuデプロイ奮闘記2(前編)

Last updated at Posted at 2021-09-22

(続編のつもりなかったんだけど...)

あまりにも苦戦したので...(笑)それと、色々タメになりそうなことも学んだので、アウトプットします!

今回の話の流れ

〜プロローグ〜 す べ て の は じ ま り
第1話 “[BUG] Segmentation fault at 0x0000000000000000” を除去
第2話 “[BUG] Segmentation fault at 0x0000000000000000” を回避
第3話 “NoMethodError: undefined method `[]' for nil:NilClass” を解決してデプロイ
第4話 Gemsass-railsを6系列にインストールし直して再度デプロイ
〜エピローグ〜 今回学んだこと

※ 前編は第2話まで

すべてを解決に導く結論

image-urlヘルパーはSassによるものなので、これを使用しているスタイルシートは、CSSではなくSCSSファイルでなければならない。これだけだった...ホントに...orz

前提条件

  • OS**:**macOS Catalina 10.15.7
  • Git**:**2.28.0
  • Heroku**:**7.59.0 darwin-x64 node-v12.21.0
  • Ruby**:**2.6.8p205 (2021-07-07 revision 67951) [x86_64-darwin19]
  • Rails**:**6.0.4.1
  • Bundler**:**1.17.2
  • Google Chrome.app**:**93.0.4577.63(Official Build)(x86_64)

デプロイ成功までの全行程
①. *config/application.rb*に`config.assets.initialize_on_precompile = false`を追記する。 →失敗:droplet: ②. *config/initializers/assets.rb*に以下を追記する。
Rails.application.config.assets.configure do |env|
  env.export_concurrent = false
end

→失敗:droplet:
③. ②の状態から、①で追記したコードを削除する。
→失敗:droplet:
④. ②で追記したコードと同じ処理をすると思われる、ワンライナー
Rails.application.config.assets.export_concurrent = false
若しくは
Sprockets.export_concurrent = false
に書き換える。
→いずれも失敗:droplet:
⑤. ④で書き換えたコードを削除して、Gemsprocketsを3系列にして再インストール。
→失敗:droplet:
⑥. ⑤のsprockets含め、関連してそうなGemを全てバージョン指定して再インストール。
→失敗:droplet: “[BUG] Segmentation fault at 0x0000000000000000” の代わりに、“Ruby Sass has reached end-of-life and should no longer be used.” のメッセージと “NoMethodError: undefined method `[]' for nil:NilClass” のエラーが出現
⑦. Gemsass-railsだけを6系列に戻して再インストール。
→失敗:droplet: “[BUG] Segmentation fault at 0x0000000000000000” が再び発生
⑧. RUNTIME依存性を考慮しつつ、関連してそうなGemのバージョンを全て固定して再インストール。
→失敗:droplet:
⑨. ⑧の状態で、①と②を繰り返す。
→いずれも失敗:droplet: “NoMethodError: undefined method `export_concurrent=' for #<Sprockets::Environment:0x00007fd14362c188>” のエラーが発生
⑩. ⑧でバージョン固定したGemsprocketsを削除する。
→失敗:droplet:
⑪. config/initializers/assets.rbに追記した②のコードを削除して、代わりにconfig/application.rbに追記する。
→失敗:droplet:
⑫. ⑨で追記した①のコードを削除して、②のコードをconfig/application.rbの色んな場所に記入してみる。
→全部失敗:droplet: “NoMethodError: undefined method `config' for nil:NilClass” のエラーが発生することも
⑬. ⑫で追記した②のコードを削除して、⑧でバージョン固定したsass-rails以外のGemを全て削除し、sass-railsは5系列にして再インストール。
→失敗:droplet:⑥と同じ結果
⑭. application.cssの拡張子を、‘.scss’、若しくは‘.css.scss’に変更する。
→いずれも失敗:droplet:
⑮. ⑭のファイルの拡張子を元の‘.css’に戻して、①を繰り返す。
→失敗:droplet:
⑯. ⑮で追記した①のコードを削除して、*app/assets/stylesheets/*以下のアセットファイルの「background-image」プロパティの値にimage-urlヘルパーを使用している部分を、引数はそのままに全てurlに変更する。
→失敗:droplet:ローカルで背景画像が表示されなくなった
⑰. ⑯の状態から、‘ url('画像ファイル名') ’を‘ url('/assets/画像ファイル名') ’に変更する。
→デプロイは成功。しかし、ローカル環境では背景画像が表示されるようになったが、Herokuリモート上では未だに反映されてないままである
⑱. config/environments/production.rbの、config.public_file_server.enabledの値を‘ true ’に変更する。
→デプロイは成功。⑰と同じ結果
⑲. config.public_file_server.enabledの値を元の‘ ENV['RAILS_SERVE_STATIC_FILES'].present? ’に戻して、「background-image」プロパティの値を‘ url('/assets/画像ファイル名') ’から‘ image-url('画像ファイル名') ’に変更し、更にこのプロパティを使用しているアセットファイルの拡張子を全て‘.scss’に変更する。
→成功 :tada: リモート環境でも背景画像が表示されるようになった
⑳. Gemsass-railsを6系列に戻して再インストール。
→成功 :tada:

※ 前編は⑫まで


〜プロローグ〜 す べ て の は じ ま り

terminal.app
remote:  !     Precompiling assets failed.

前回苦戦した時と同じく、プリコンパイルによるエラーが発生した。しかも、今回のログは非常になが〜く、特に色を付けて強調してある部分もなかったが、注意深く読んでみると...

/tmp/build_91b02c90/vendor/bundle/ruby/2.6.0/gems/sassc-2.4.0/lib/sassc/engine.rb:43: [BUG] Segmentation fault at 0x0000000000000000
ruby 2.6.8p205 (2021-07-07 revision 67951) [x86_64-linux]

という一文を発見!**“[BUG]”**と記されている通り、「ここにバグがありますよ」と言っている(他にも警告しているメッセージが幾つか見つかったが、今回はどれも無視して良さそうなものばかりだった)。また、こちらのかたの記事によると、上のエラーが発生した場合は以下のコマンドを実行してみれば良さそうだ。

terminal.app
開発環境内にエラーが無いかを確認
% RAILS_ENV=development bin/rails assets:precompile

本番環境内にエラーが無いかを確認
% RAILS_ENV=production bin/rails assets:precompile

これらにより、各環境内のエラー箇所を分析することができる。早速試してみると、普通にデプロイするコマンドを実行したときよりも短いログが出力され、上と同じように

[BUG] Segmentation fault at 0x0000000000000000
ruby 2.6.8p205 (2021-07-07 revision 67951) [x86_64-linux]

の一文を見つけることができた。エラーの原因となる部分がどこにあるのかよく分からない場合は、まずはこのコマンドを叩いてみれば良いかもしれない。デプロイする前に試験的に実行してみるのもアリだ。
さて、このバグを取り除けば動くようになるんじゃなかろうか?...という事で、ここから色々調べまくるのだが、まずはこの**Segmentation fault(セグメンテーション違反、通称セグフォ)**というものが何なのか?どうやらこれはメモリ操作時に発生するバグのようだ。詳しく知りたかったらC言語とかをもっと勉強するとして、このエラーの解決に注力することにする。

第1話 “[BUG] Segmentation fault at 0x0000000000000000” を除去

まずは、先程と同じ記事に記載されている、解決法の一つである

config/application.rb
config.assets.initialize_on_precompile = false    # Applicationクラス内に追加

これを試す。アセットパイプラインを正常化させるためのものらしい。そして、RAILS_ENV=production bin/rails assets:precompileを実行。どうやらこれらのエラーチェックのコマンドは、各環境でプリコンパイルするためのもののようだ。以降、デプロイ用のコマンドgit push heroku master、若しくはgit push heroku ‘トピックブランチ名’:masterを実行するのは、これらのプリコンパイル用のコマンドを使用して異常が無いことを確認してからにする。

バグが直らなかったので、今度はこちらのかたの記事等に記載されているコード

config/initializers/assets.rb
Rails.application.config.assets.configure do |env|
  env.export_concurrent = false
end

を追加してみる。何のことだかさっぱり訳が分からないのだが、CSSやimageなどのファイルのデフォルトのコンパイラであるsprockets1が、バージョン4.0から並列処理を行うようになったのでそれを無効にするための設定らしい。

しかし、これを試してもうまくいかなかったので、上の3行の代わりにこちらのかたの記事に載っているコード

config/initializers/assets.rb
Rails.application.config.assets.export_concurrent = false
# 若しくは
Sprockets.export_concurrent = false

を追記したりしたが、結局記法を変えただけなので意味がなかった。

別の方法を考える必要がある。そこで、Gemsprocketsのバージョン3系列を代わりに使用してみることにした。

Gemfile
+ gem 'sprockets', '~> 3.0'

結果は変わらず...次に、Stack Overflowのこちらの質問に対するベストアンサーに記載されている通りに、各Gemをバージョンをそのまま素直に指定してインストールした。

Gemfile
- gem 'sass-rails', '~> 6'
+ gem 'sass-rails', '~> 5.1.0'
 (中略)
- gem 'sprockets', '~> 3.0'
+ gem 'sassc', '~> 2.0', '>= 2.0.1'
+ gem 'sprockets', '~> 3.7.2'
+ gem 'concurrent-ruby', '~>1.1.5'

...すると、エラーは出たものの、いつもと違う結果になった。

第2話 “[BUG] Segmentation fault at 0x0000000000000000” を回避

rake aborted!
NoMethodError: undefined method `[]' for nil:NilClass

バグではなく、代わりに上のエラーが発生した。進展あったのか..?ここで試しにあえてデプロイコマンドを打つと

Ruby Sass has reached end-of-life and should no longer be used.

「Ruby Sassはもうオワコンだから使っちゃダメだよ」と注意された。これの解決策は色々あるみたいだが、ここでは一番シンプルにこちらのかたの記事に載っている対処方法のように、Gemsass-railsを元の6系列に戻す。

Gemfile
- gem 'sass-rails', '~> 5.1.0'
+ gem 'sass-rails', '~> 6'

すると...

[BUG] Segmentation fault at 0x0000000000000000
ruby 2.6.8p205 (2021-07-07 revision 67951) [x86_64-linux]

またセグフォバグが出てきてしまった:droplet:

(ここで、この変更を元に戻してNoMethodErrorの解決にシフトすれば良かったのだが...)

どうにもうまくいかないので、今度はこちらのsassc-rubyのIssueに対するコメントに記載されている通りに、sassc-rubyを含めた各Gemのバージョンをそのまま素直に固定指定させ、且つRUNTIME(ランタイム)依存性2を考慮して、sass-railsのバージョン6.0.0.beta2を代わりに指定してそれぞれインストールし直した。

Gemfile
- gem 'sass-rails', '~> 6'
+ gem 'sass-rails', '6.0.0.beta2'
 (中略)
- gem 'sassc', '~> 2.0', '>= 2.0.1'
- gem 'sprockets', '~> 3.7.2'
- gem 'concurrent-ruby', '~>1.1.5'
+ gem 'sassc', '2.0.1'
+ gem 'sassc-rails', '2.1.0'
+ gem 'sprockets', '3.7.2'
+ gem 'concurrent-ruby', '1.1.5'

デプロイできなくて同じ症状で悩んでいる人が海外にも多数いる事を知って安心したのも束の間、全く効果が無くて絶望した。この辺からだんだん自暴自棄になってきてしまい、どうにもこうにもうまくいかないので、Gemfileが上の状態で第1話でやった事を繰り返してみた(『デプロイ成功までの全行程』の①と②)。すると

NoMethodError: undefined method `export_concurrent=' for #<Sprockets::Environment:0x00007fd14362c188>

export_concurrent=メソッドが定義されていない」という新しいエラーが発生した。これは、このexport_concurrent=メソッドが定義されているファイルsprockets/lib/sprockets/exporting.rbが、現在のバージョン3.7.2に存在していないが故に起こっているため、最新のバージョン4.0.2にインストールし直した。

Gemfile
- gem 'sprockets', '3.7.2'

しかし、ここまでやってもセグフォバグは未だに解消しきれなくて、もうこの際だから何でもやってやろうと思い、先程のsassc-rubyのIssueに対する別のかたのコメントにあるように、並列処理無効化のためのコード

config/initializers/assets.rb
Rails.application.config.assets.configure do |env|
  env.export_concurrent = false
end

を、config/application.rbの方へ書き換えてみる(そもそもこのコードはGemsprocketsがバージョン4.0以降から使える設定なので、3系列以前に並列処理関連のファイルが無いのは当たりm...)。ただ、このファイル内のどこに書き込めば良いのかまでは分からなかったので、我武者羅に

config/application.rb
require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

# ココだったり

module ‘アプリ名’
  class Application < Rails::Application
    
    config.load_defaults 6.0

    # ココだったり

    config.generators do |g|
      g.stylesheets false
      g.javascripts false
      g.helper false
      g.test_framework false
    end

  end

  # ココだったり

end

# ココ

といった具合に、色んな箇所に記入してみた。案の定バグは直らず、書き込んだ場所によっては

NoMethodError: undefined method `config' for nil:NilClass

「NilClassにconfigメソッドが定義されていない」というエラーが無駄に発生してしまった。そりゃそうだよなぁと思いつつ、流石にやりすぎた感があるため、ここまで編集した作業を全て元に戻した。追加したGemも全て削除。セグフォバグの除去は現段階じゃ不可能だと諦め、あえてGemsass-railsの5系列を再インストールして、NoMethodErrorのデバッグを決心したのであった...(続く)

Gemfile
- gem 'sass-rails', '6.0.0.beta2'
+ gem 'sass-rails', '~> 5'
 (中略)
- gem 'sassc', '2.0.1'
- gem 'sassc-rails', '2.1.0'
- gem 'concurrent-ruby', '1.1.5'

次回予告

果たしてデプロイは成功するのだろうか...?

次回!Herokuデプロイ奮闘記2(後編)

参考記事

関連投稿記事

  1. Rails 6.0からJavaScriptのデフォルトのコンパイラはwebpackerとなっている。

  2. 実行時によるGemの依存性をRUNTIME依存性、開発時によるGemの依存性をDEVELOP(MENT)依存性というらしい。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?