(続編のつもりなかったんだけど...)
あまりにも苦戦したので...(笑)それと、色々タメになりそうなことも学んだので、アウトプットします!
今回の話の流れ
〜プロローグ〜 す べ て の は じ ま り
第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)
デプロイ成功までの全行程
Rails.application.config.assets.configure do |env|
env.export_concurrent = false
end
→失敗
③. ②の状態から、①で追記したコードを削除する。
→失敗
④. ②で追記したコードと同じ処理をすると思われる、ワンライナー
Rails.application.config.assets.export_concurrent = false
若しくは
Sprockets.export_concurrent = false
に書き換える。
→いずれも失敗
⑤. ④で書き換えたコードを削除して、Gemsprockets
を3系列にして再インストール。
→失敗
⑥. ⑤のsprockets
含め、関連してそうなGemを全てバージョン指定して再インストール。
→失敗 “[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系列に戻して再インストール。
→失敗 “[BUG] Segmentation fault at 0x0000000000000000” が再び発生
⑧. RUNTIME依存性を考慮しつつ、関連してそうなGemのバージョンを全て固定して再インストール。
→失敗
⑨. ⑧の状態で、①と②を繰り返す。
→いずれも失敗 “NoMethodError: undefined method `export_concurrent=' for #<Sprockets::Environment:0x00007fd14362c188>” のエラーが発生
⑩. ⑧でバージョン固定したGemsprockets
を削除する。
→失敗
⑪. config/initializers/assets.rbに追記した②のコードを削除して、代わりにconfig/application.rbに追記する。
→失敗
⑫. ⑨で追記した①のコードを削除して、②のコードをconfig/application.rbの色んな場所に記入してみる。
→全部失敗 “NoMethodError: undefined method `config' for nil:NilClass” のエラーが発生することも
⑬. ⑫で追記した②のコードを削除して、⑧でバージョン固定したsass-rails
以外のGemを全て削除し、sass-rails
は5系列にして再インストール。
→失敗⑥と同じ結果
⑭. application.cssの拡張子を、‘.scss’、若しくは‘.css.scss’に変更する。
→いずれも失敗
⑮. ⑭のファイルの拡張子を元の‘.css’に戻して、①を繰り返す。
→失敗
⑯. ⑮で追記した①のコードを削除して、*app/assets/stylesheets/*以下のアセットファイルの「background-image」プロパティの値にimage-url
ヘルパーを使用している部分を、引数はそのままに全てurl
に変更する。
→失敗ローカルで背景画像が表示されなくなった
⑰. ⑯の状態から、‘ 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’に変更する。
→成功 リモート環境でも背景画像が表示されるようになった
⑳. Gemsass-rails
を6系列に戻して再インストール。
→成功
※ 前編は⑫まで
〜プロローグ〜 す べ て の は じ ま り
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]”**と記されている通り、「ここにバグがありますよ」と言っている(他にも警告しているメッセージが幾つか見つかったが、今回はどれも無視して良さそうなものばかりだった)。また、こちらのかたの記事によると、上のエラーが発生した場合は以下のコマンドを実行してみれば良さそうだ。
開発環境内にエラーが無いかを確認
% 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.assets.initialize_on_precompile = false # Applicationクラス内に追加
これを試す。アセットパイプラインを正常化させるためのものらしい。そして、RAILS_ENV=production bin/rails assets:precompile
を実行。どうやらこれらのエラーチェックのコマンドは、各環境でプリコンパイルするためのもののようだ。以降、デプロイ用のコマンドgit push heroku master
、若しくはgit push heroku ‘トピックブランチ名’:master
を実行するのは、これらのプリコンパイル用のコマンドを使用して異常が無いことを確認してからにする。
バグが直らなかったので、今度はこちらのかたの記事等に記載されているコード
Rails.application.config.assets.configure do |env|
env.export_concurrent = false
end
を追加してみる。何のことだかさっぱり訳が分からないのだが、CSSやimageなどのファイルのデフォルトのコンパイラであるsprockets
1が、バージョン4.0から並列処理を行うようになったのでそれを無効にするための設定らしい。
しかし、これを試してもうまくいかなかったので、上の3行の代わりにこちらのかたの記事に載っているコード
Rails.application.config.assets.export_concurrent = false
# 若しくは
Sprockets.export_concurrent = false
を追記したりしたが、結局記法を変えただけなので意味がなかった。
別の方法を考える必要がある。そこで、Gemsprockets
のバージョン3系列を代わりに使用してみることにした。
+ gem 'sprockets', '~> 3.0'
結果は変わらず...次に、Stack Overflowのこちらの質問に対するベストアンサーに記載されている通りに、各Gemをバージョンをそのまま素直に指定してインストールした。
- 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系列に戻す。
- 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]
またセグフォバグが出てきてしまった
(ここで、この変更を元に戻してNoMethodErrorの解決にシフトすれば良かったのだが...)
どうにもうまくいかないので、今度はこちらのsassc-rubyのIssueに対するコメントに記載されている通りに、sassc-ruby
を含めた各Gemのバージョンをそのまま素直に固定指定させ、且つRUNTIME(ランタイム)依存性2を考慮して、sass-railsのバージョン6.0.0.beta2を代わりに指定してそれぞれインストールし直した。
- 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にインストールし直した。
- gem 'sprockets', '3.7.2'
しかし、ここまでやってもセグフォバグは未だに解消しきれなくて、もうこの際だから何でもやってやろうと思い、先程のsassc-rubyのIssueに対する別のかたのコメントにあるように、並列処理無効化のためのコード
Rails.application.config.assets.configure do |env|
env.export_concurrent = false
end
を、config/application.rbの方へ書き換えてみる(そもそもこのコードはGemsprockets
がバージョン4.0以降から使える設定なので、3系列以前に並列処理関連のファイルが無いのは当たりm...)。ただ、このファイル内のどこに書き込めば良いのかまでは分からなかったので、我武者羅に
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のデバッグを決心したのであった...(続く)
- 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'
次回予告
果たしてデプロイは成功するのだろうか...?
参考記事
- エラー解決法|Rails
- アセットパイプライン | Rails日本語ドキュメント | Ruby STUDIO
- エラー「...mysql2/client.rb:90: [BUG] Segmentation fault at 0x00000000000000」(セグフォ/セグメンテーション違反)に対応した - K’s diary
- 【エラー解消メモ】[BUG] Segmentation fault - Ruby on Rails Learning Diary
- gem 'sprockets' 4.0での並列処理でデッドロックしてしまう問題について - Qiita
- sass-railsを使っていて"Ruby Sass has reached end-of-life and should no longer be used."とエラーが表示されたら - s4naのテックブログ
- Can't push to heroku, sassc segmentation fault
- segfault on 2.3.0 · Issue #197 · sass/sassc-ruby
- sass-rails | RubyGems.org | コミュニティのGemホスティングサービス
- GitHub - rails/sprockets: Rack-based asset packaging system
- あなたの知ってるRubyGemsTipsというイベントでGemの依存関係まわりの話でLTしました💎 - Madogiwa Blog