LoginSignup
1
0

More than 1 year has passed since last update.

Herokuデプロイ奮闘記(後編)

Last updated at Posted at 2021-06-04

これは、度重なるエラーに苦戦しながらも初めてのHerokuデプロイに成功した、ある一人の男の物語である。

結論(デプロイまでの過程)

  1. Rubyの3.0.1をインストールしてバージョン変更。
  2. 更にRubyの2.7.3をインストールしてもう一度バージョン変更。Bundlerの2.2.17をインストールしてこっちもバージョン変更。
  3. 更にBundlerの2.2.16をインストールしてこっちももう一度バージョン変更(Heroku環境に合わせるため)。このバージョンでbundle install
  4. BundlerをPCの環境に合わせるために、コマンドbundle lock --add-platform x86_64-linuxを実行。
  5. devisekaminariの各Gemを開発・テスト・本番の全ての環境で使えるようにする。
  6. config/environments/production.rbconfig.assets.js_compressor = :uglifierの行をコメントアウトして、テンプレートリテラルを認識させる。
  7. app/assets/stylesheets/style.scss先頭の@import compass;をコメントアウト。
  8. app/assets/stylesheets/style.scss先頭の@import compass;のコメントを外して(元に戻して)、Gemのcompass-railsを開発・テスト・本番の全ての環境で使えるようにする。
  9. デプロイ完了!!

※今回も長くなりそう(なった)なので、前半と後半に記事を分けて書きます。

前提条件

  • macOS Catalina ( 10.15.71 )
  • Rails ( 5.2.61 )
  • Terminal.app ( 2.101 )
  • Ruby ( 2.7.32 )
  • Bundler ( 2.2.162 )
  • Google Chrome.app( 91.0.4472.771 )
  • Visual Studio Code.app( 1.56.21 )

本題

5. deviseとkaminariの各Gemを全環境で使えるようにする

なかなかそう簡単にはデプロイさせてくれない...

terminal.app
remote:  !
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed

出力されるエラーメッセージは多種多様だが、英単語を知ってれば自ずと読めるようになる。大事な部分は違う色などで強調して教えてくれるから、その付近を注視すれば成功したのか失敗したのかを把握する事は可能(但し、必ずしもそうとは限らないので注意)。上の6行だと、先頭3行が

remote: !
remote: ! Precompiling assets failed.
remote: !

というように、赤色で表示されていた。何だかよく分からんけど、「アセットのプリコンパイルに失敗した」から結果的にプッシュ(デプロイ)に失敗したと言っている事が分かる。ところで、この「プリコンパイル」とは一体何なのか?こちらのIT用語辞典では、

プリプロセッサとは、ソフトウェアの役割による分類の一つで、ある中心的な処理を行うプログラムに対して、その前処理(preprocess)3を行うプログラムのこと。プログラミング言語のコンパイラの前処理を行うものが非常に有名。

と説明している。この通りなんだろうが、要はコンパイラがコンパイル4しやすいように、ちょっとソースコードを改変する作業のこと。

  • 外部ファイルの読み込み
  • 文字列の置換
  • 条件分岐処理

などなど。大学でCやJavaを少し習ったけど、その時に起こしてたコンパイルエラーは、このプリコンパイルが正しく処理されたのを前提とした上で発生したものだったのだろうか...?だとしたら解決策も変わってくる筈だ。出力されたメッセージを上から注意して見ていくと、

terminal.app
remote:        Bundle completed (25.86s)
remote:        Cleaning up the bundler cache.
remote: -----> Installing node-v12.16.2-linux-x64
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        rake aborted!
remote:        NameError: uninitialized constant Devise

(以下略)

エラーの発生箇所を発見!「Bundle completed」とあるから、Gemの読み込みは完了したっぽい。問題はその後に起きたようだ。ここで「NameError: uninitialized constant Devise」でググってみたら、見事に解決方法が記述されているこちらの方の記事を見つけた。どうやら本番環境でGemが使えるように設定されてなかったのが原因だったようだ。そんな馬鹿な...と思ってGemfileを見てみたら、group :development, :test do ... endの中にしっかりとセットしてますた(笑)早速deviseと、ついでにページネーション5実装時に使用するkaminariもこのグループから取り出して、ファイルの最下部に書き直した。

Gemfile
(省略)

  group :development, :test do
    # Call 'byebug' anywhere in the code to stop execution and get a debugger console
    gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

    gem 'pry-rails'
    gem 'compass-rails', '3.1.0'
    gem 'sprockets', '3.7.2'
-   gem 'devise'
-   gem 'kaminari'
    gem 'rspec-rails'
    gem 'rails-controller-testing'
    gem 'factory_bot_rails'
    gem 'faker', '~> 2.8'
  end

(省略)

  # Use jquery as the JavaScript library
  gem 'jquery-rails'

# 最下部に追加
+ gem 'devise'
+ gem 'kaminari'

【別解】若しくは下のように、開発・テスト・本番の3つの環境によるグループを作成してその中に入れ込む。

Gemfile
(省略)

  group :development, :test do
    # Call 'byebug' anywhere in the code to stop execution and get a debugger console
    gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

    gem 'pry-rails'
    gem 'compass-rails', '3.1.0'
    gem 'sprockets', '3.7.2'
-   gem 'devise'
-   gem 'kaminari'
    gem 'rspec-rails'
    gem 'rails-controller-testing'
    gem 'factory_bot_rails'
    gem 'faker', '~> 2.8'
  end

(省略)

  group :production do
    gem 'rails_12factor'
  end

# 全運用環境によるグループを作成
+ group :development, :test, :production do
+   gem 'devise'
+   gem 'kaminari'
+ end

(省略)

そりゃプリコンパイルできない訳だ...まぁ当時は本番環境のことを何も考慮してなかったから仕方ない...orz
因みに「NameError: uninitialized constant Devise」というエラーを見て、「Devise」が最初Gemのdeviseのことだと思わず、電子デバイスかなんかと勘違いしちゃって「ハードの問題か!?」とちょっと焦っちまったのは内緒...❤️

6. テンプレートリテラル記法を認識させる

さぁ、今回も楽しいたのしいデプロイチャレンジの時間がやって参りました!(白目)

terminal.app
ログインしてなかったらログインする
% heroku login --interactive

コードの全修正をインデックスに追加
% git add .

Let's commit!
% git commit -m “コミットメッセージ”

デプロイリベンジ
% git push heroku master 

結果は...?

terminal.app
remote:  !
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed

ぐぬぬ...同じエラーか...しかし、メッセージを遡って読んでみると

terminal.app
remote:        rake aborted!
remote:        Uglifier::Error: Unexpected character '`'

(以下略)

良かった...少しは進展があったようだ。「予期してない文字『`』」というUglifier6によるエラー。
この解決策もこちらの方の記事に一緒に記述されてあった。このバッククオート`は無論テンプレートリテラルによるものである。この記法を認識させるには、

config/environments/production.rb
(省略)
  # Compress JavaScripts and CSS.
- config.assets.js_compressor = :uglifier
+ # config.assets.js_compressor = :uglifier  ←この行をコメントアウト
  # config.assets.css_compressor = :sass
(省略)

これだけでOK。

7. Gemのcompass-railsを無効にするつもりだった(意味のない変更)

:warning: このstepは完全に誤りです。恥ずかしいので無視してもらってかまいませんが、変更部分は一応記述しておきます。

terminal.app
remote:  !
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed

はい、またまたプリコンパイル失敗...。めげずにstep.5step.6と同様に出力メッセージを辿ってみる。

terminal.app
remote:        rake aborted!
remote:        Sass::SyntaxError: File to import not found or unreadable: compass.

(以下略)

お次は「インポートするcompassファイルが見つからないか読み取れない」というSyntaxError(構文エラー)。なぜか「見つからないなら無効にして無かった事にすれば良いじゃん!」と安直に考えてしまい、

app/assets/stylesheets/style.scss
- @import "compass";
+ // @import "compass";  ←先頭の第1行をコメントアウト

  /*
 * "ほのか明朝" licensed under the IPA Font License Agreement v1.0
 * http://fontfree.me/966(配布元のURL)
 * http://ipafont.ipa.go.jp/(IPAフォントのURL)
 * http://ipafont.ipa.go.jp/ipa_font_license_v1.html(IPAフォントライセンスv1.0のURL)
 */

(以下略)

てやっちゃった!(・ω < )使用するためにインストールした筈なのに...

8. step.7による変更を元に戻して、Gemのcompass-railsを全環境で使えるようにする

terminal.app
remote:        rake aborted!
remote:        Sass::SyntaxError: Undefined mixin 'transition-property'.

(以下略)

内容が変わってるから少しずつゴールには向かっているのだろうけど、いつになったらこの「Precompiling assets failed.」のエラーから抜け出せるのか...先程と同じくSassによるSyntaxErrorだが、今度は「定義されてないmixin『transition-property』」とのこと。
フロントエンド学習時に少し出てきたけど、ちょっとだけ復習...。変数は値を定義するものだが、このmixinとはスタイルを定義するものである。これを利用すれば、何度も同じスタイルを使い回す事ができる。例えばセレクタの.clearfixはよく使われる可能性のあるスタイルなので、

sample_style.scss
@mixin clearfix() {
  &:after {
    clear: both;
    display: block;
    content: "";
  }
}

みたいに事前に定義しておき、必要になったら@includeを用いて

sample_style.scss
@include clearfix();

とすれば毎回呼び出す事ができる。さてさて、そんじゃ今回のスタイルシートで、mixinのtransition-propertyを呼び出している箇所を見てみるか...

app/assets/stylesheets/style.scss
(省略)
.transition {
  @include transition-property(all);
  @include transition-duration(0.2s);
  @include transition-timing-function(linear);
}
(省略)

あったあった。どうやら他にもtransition-durationtransition-timing-functionというmixinも併せて定義して、ここで一緒に呼び出しているようだ。ではこれらのmixinを定義している箇所も見てみるか...あれ?無いぞ!?command + pで検索しても見つからない。別ファイルに定義してある訳でもなさそうだ...どうやらこれはGemのcompass-railsが関係しているらしい。そもそもこの『compass』って何だろう?

ちょっとググってみると、CSSを効率的に作成できるように設計されたSass用のフレームワークとのこと。多数のmixinや関数がライブラリ化してあり、色んな機能を提供してくれる。ここで、VSCodeから検索のサイドバーを開いて、上の検索ボックスにtransition-propertyと入力し、これと同じ記述がしてあるコードを含むファイルがあるかどうかを調べてみると、

app/assets/stylesheets/setting.css
省略
.animate {
  -moz-transition-property: all;
  -o-transition-property: all;
  -webkit-transition-property: all;
  transition-property: all;
  -moz-transition-duration: 0.2s;
  -o-transition-duration: 0.2s;
  -webkit-transition-duration: 0.2s;
  transition-duration: 0.2s;
  -moz-transition-timing-function: ease-in;
  -o-transition-timing-function: ease-in;
  -webkit-transition-timing-function: ease-in;
  transition-timing-function: ease-in;
}
省略

発見した!ベンダープレフィックス7が付いてるのもあれば、そのまま使えるのもあるっぽい。これらはstep.7でコメントアウトした@import "compass";により、モジュールとして読み込む事ができる。と言うことは、やっぱりこれを無効化するのは間違いだったか...
このGemについて理解しようとすると、俗に言うHTML/CSSの沼にまたハマってしまうこと間違い無しなので(笑)、とにかくエラーの解決に集中。step.7で付け加えたコメントを外して、「ローカル環境では普通に使えてたんだから、リモートでも使えるようにすれば良いだけじゃないのか」という正しい解釈に至った。

app/assets/stylesheets/style.scss
- // @import "compass";
+ @import "compass";     ←先頭の第1行のコメントを外す

  /*
 * "ほのか明朝" licensed under the IPA Font License Agreement v1.0
 * http://fontfree.me/966(配布元のURL)
 * http://ipafont.ipa.go.jp/(IPAフォントのURL)
 * http://ipafont.ipa.go.jp/ipa_font_license_v1.html(IPAフォントライセンスv1.0のURL)
 */

(以下略)

step.5と同様に、開発・テストの両環境のグループからcompass-railsを取り出して、ファイルの最下部に書き直す。ついでにアセットパイプライン8というものを実装するためのsprocketsというGemも、一緒に外に出しとくか。多分、問題無いだろう...

Gemfile
(省略)

  group :development, :test do
    # Call 'byebug' anywhere in the code to stop execution and get a debugger console
    gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

    gem 'pry-rails'
-   gem 'compass-rails', '3.1.0'
-   gem 'sprockets', '3.7.2'
    gem 'rspec-rails'
    gem 'rails-controller-testing'
    gem 'factory_bot_rails'
    gem 'faker', '~> 2.8'
  end

(省略)

  # Use jquery as the JavaScript library
  gem 'jquery-rails'

# 最下部に追加
+ gem 'compass-rails', '3.1.0'
+ gem 'sprockets', '3.7.2'
  gem 'devise'
  gem 'kaminari'

【別解】若しくは下のように、開発・テスト・本番の3つの環境によるグループの中に入れ込む。

Gemfile
(省略)

  group :development, :test do
    # Call 'byebug' anywhere in the code to stop execution and get a debugger console
    gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

    gem 'pry-rails'
-   gem 'compass-rails', '3.1.0'
-   gem 'sprockets', '3.7.2'
    gem 'rspec-rails'
    gem 'rails-controller-testing'
    gem 'factory_bot_rails'
    gem 'faker', '~> 2.8'
  end

(省略)

  group :production do
    gem 'rails_12factor'
  end

# 全運用環境によるグループを作成
  group :development, :test, :production do
+   gem 'compass-rails', '3.1.0'
+   gem 'sprockets', '3.7.2'
    gem 'devise'
    gem 'kaminari'
  end

(省略)

9. 感動のフィナーレ

それは、一番下の方に記されてあった...

terminal.app
remote: Verifying deploy... done.

で...できたー!:joy: 正直この流れだとまだ続きそうな感じだったが、ようやくこの闘いに終止符が打たれた。厳密に言うと、少しこの上の方に

terminal.app
remote: ###### WARNING:
remote: 
remote:        No Procfile detected, using the default web server.
remote:        We recommend explicitly declaring how to boot your server process via a Procfile.
remote:        https://devcenter.heroku.com/articles/ruby-default-web-server

と表示されてあるが、多分現段階だと無視しても問題無い警告メッセージだろう。

今回学んだこと

  • デプロイに対して牧歌的すぎた。ちょっとナメてた。
  • 環境構築時以外でも、バージョンや依存関係は常に意識しておく。
  • 新しいGemをインストールする際は、どの環境で運用させるべきかを予め把握しておく必要がある。
  • エラーログに目立つ色で強調表示してある部分は重要なメッセージが記されている。そうじゃない部分にも重要なメッセージが記されている。
  • やっぱり英語は大事。

今回はこの程度の変更修正で済んだけど、下手したらもっと多くのエラーが出て、もっと時間を費やす羽目になっていたかもしれない。こんな形で備忘録として残しておいて、同じようなエラーが発生したら直ぐに対処できるようにしておきたい。

これをもって、初めてのHerokuデプロイが完了したことにする。

参考記事

関連投稿記事


  1. ブログ執筆時のバージョン 

  2. step.4後段階のバージョン 

  3. 逆に、メインの処理に対する後処理を行うものをポストプロセッサというらしい。これは、いわゆるインタプリタとかを指すのかな? 

  4. プログラミング言語で書かれたソースコードを解釈して、そのソースコードを今度はコンピュータが解釈、且つ実行できるネイティブコード(若しくはバイトコード)に変換する翻訳作業のこと。 

  5. 長い文章を複数のページに分割して、各ページへのリンクを並べアクセスしやすくする機能。Googleなんかの検索結果のページの下に表示されてるアレ。 

  6. Railsに標準で搭載されているJavaScript軽量化のライブラリのことらしい。これは英語の『醜くする』という意味の『uglify』が由来っぽい? 

  7. CSSでプロパティや値を指定する際に、各ブラウザのメーカーさんが独自に拡張した機能を呼び出すために付けられる接頭辞のこと。 

  8. JavaScriptやCSSなどのアセットを最小化または圧縮化して連結するためのフレームワークのことらしい。 

1
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
1
0