Heroku での Rails アセットパイプライン
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2020年12月15日(火)
Table of Contents
Heroku で実行されている Rails アプリケーションは、ローカルで、デプロイ時に、または実行時にアセットパイプラインをコンパイルできます。新規ユーザーの方は、次に進む前に「Heroku スターターガイド (Ruby)」をお読みになることをお勧めします。
Heroku では、エンドユーザーエクスペリエンスを向上させて Heroku アプリの負荷を軽減するために、CDN でアセットパイプラインを使用することを推奨しています。
Rails 4 アセットパイプライン
Rails 4 とアセットパイプラインを使用している場合、以下のドキュメントの内容を理解することをお勧めします。Rails 3 と Rails 4 の間では多くの動作が似ています。読み終えたら、2 つのエクスペリエンスの違いについて説明している「Heroku での Rails 4 アセットパイプライン」をお読みください。
Rails 3 アセットパイプライン
Rails 3 アセットパイプラインは、Heroku のスタックでサポートされています。新しいパイプラインにより、Rails スタックでのアセットの扱いが向上します。Rails ではデフォルトで、JavaScript には CoffeeScript を、CSS には SCSS を使用します。RailsConf 基調講演での David Heinemeier Hansson による解説もご覧ください。
Rails アセットパイプラインが提供する assets:precompile
rake タスクは、アプリを起動するたびにアセットをコンパイルするのではなく、アセットを事前にコンパイルおよびキャッシュしておくためのものです。
Heroku では 2 通りの方法でアセットパイプラインを使用できます。
- アセットをローカルでコンパイルする。
- slug のコンパイル中にアセットをコンパイルする。
アセットをローカルでコンパイルする
public/assets/manifest.yml
がアプリで検出された場合、Heroku はアセットのコンパイルが開発者によって処理されると想定し、アセットのコンパイルを試みません。Rails 4 では、代わりに public/assets/manifest-<md5 hash>.json
というファイルを使用します。最近のバージョンでは public/assets/.sprockets-manifest-<md5 hash>.json
を使用します (ドット .
は、マシン上でデフォルトで非表示になる場合があることを示します)。どのバージョンでも、ローカルで $ rake assets:precompile
を実行し、結果のファイルを Git にチェックインすることによってこのファイルを生成できます。
アセットをローカルでコンパイルするには、ローカルで assets:precompile
タスクをアプリに対して実行します。アセットの本番バージョンが生成されるよう、必ず production
環境を使用してください。
RAILS_ENV=production bundle exec rake assets:precompile
public/assets
ディレクトリが作成されます。このディレクトリ内には、Rails 3 のコンパイル済みアセットの md5sum を含む manifest.yml
があります。Rails 4 では、ファイルは manifest-<md5 hash>.json
になります。public/assets
を Git リポジトリに追加すると、Heroku で利用可能になります。
git add public/assets
git commit -m "vendor compiled assets"
ここでプッシュを行うと、ローカルでコンパイルしたアセットが検出されたという情報が出力されます。
-----> Preparing Rails asset pipeline
Detected manifest.yml, assuming assets were compiled locally
slug のコンパイル中にアセットをコンパイルする
アセットをローカルでコンパイルしていない場合、slug のコンパイル中に assets:precompile
タスクの実行が試みられます。プッシュの出力は次のようになります。
-----> Preparing Rails asset pipeline
Running: rake assets:precompile
slug のコンパイルプロセスの間に rake タスクがどのように機能するかの説明は、この後の「トラブルシューティング」のセクションを参照してください。
失敗した assets:precompile
assets:precompile
タスクが失敗した場合、出力が表示されてビルドは終了します。
アセットのキャッシング
静的アセットのキャッシングは、アプリケーション内で Rack::Cache ミドルウェアを使用して実装するか、CDN を使用してより分散性を高めた方法で実装することができます。アプリケーションからのアセットの提供には dyno リソースが必要なため、ニーズに合った適切なアセットキャッシング戦略を検討してください。
トラブルシューティング
assets:precompile タスクの失敗
Rails 3.x では、config/application.rb
に次の行を配置することで、アプリケーションの初期化とデータベースへの接続を防ぐことができます。
config.assets.initialize_on_precompile = false
この設定を変更した後は、必ず Git にコミットしてください。
アセットは、ローカルでコンパイル可能にならない限り Heroku でコンパイルできません。次のコマンドを実行してアセットをデバッグします。
$ RAILS_ENV=production bundle exec rake assets:precompile
エラーが発生することなく完了すれば問題ありません。このコマンドの実行後、アセットを Git にチェックインしないでください。
therubyracer
以前に therubyracer
または therubyracer-heroku
を使用していた場合、これらの gem は不要になりました。また、これらの gem はメモリ使用量が多すぎるため、使用しないことを強く推奨します。
アセットのコンパイルに使用される Ruby buildpack によって Node のバー ジョンがインストールされます。
PATH の更新
アセットを実行時にコンパイルする必要がある場合、JavaScript ランタイムにアクセスするために bin
を PATH に追加する必要があります。heroku config
を使用して現在の設定を確認します。
$ heroku config
PATH => vendor/bundle/ruby/1.9.1/bin:/usr/local/bin:/usr/bin:/bin
PATH 変数に bin
が単独で含まれていない場合、次のように実行して更新します。
$ heroku config:set PATH=bin:vendor/bundle/ruby/1.9.1/bin:/usr/local/bin:/usr/bin:/bin
Adding config vars:
PATH => vendor/bundle/ru...usr/bin:/bin:bin
Restarting app... done, v7.
デバッグ出力が何もない
デバッグ出力が表示されず asset:precompile
タスクが実行されない場合は、rake
が Gemfile
内にあり、適切にコミットされていることを確認してください。
本番環境でコンパイルを True に設定
本番環境でアプリケーションの config.assets.compile = true
を有効にすると、アプリケーションが非常に低速になる場合があります。この状況は、Stack Overflow の投稿で最もわかりやすく説明されています。
コンパイルをオンにすると、次のような動作になります。 /assets 内のファイルに対するすべてのリクエストは Sprockets に渡されます。すべての個別アセットに対する最初のリクエスト時に、アセットがコンパイルされ、Rails がキャッシュに使用している場所 (通常はファイルシステム) にキャッシュされます。 次回以降のリクエストでは、Sprockets はリクエストを受け取り、フィンガープリント入りのファイル名を検索し、アセットを構成するファイル (イメージ、または css と js) が変更されていないことを確認し、キャッシュされたバージョンがある場合はそのバージョンを提供します。
この設定は、実行時にその他の不安定な動作の原因になることも知られているため、通常は推奨されません。代わりに、すべてのアセットをデプロイ時に事前コンパイルする (デフォルト) か、それが不可能な場合はローカルでアセットをコンパイルすることをお勧めします。