Skip to content

Rails asset pipeline

shunter1112 edited this page Sep 14, 2013 · 4 revisions

HerokuのCedarスタック上で動くRailsアプリケーションはアセットパイプラインをローカルかデプロイ時、もしくは実行時にコンパイルした状態にすることができます。新しいユーザの方ならば、この先を進める前にCedar上でRails 3.xのアプリケションを作るためのチュートリアルを読む事をおすすめします。

環境変数は、コンパイル時には利用可能ではありません。これは、アセットのコンパイル時にこれらが必要になった場合にタスクが適切に実行されない事を意味します。ベストプラクティスとして、アプリケーションをコンパイル時に環境変数を必要としない形に書き換える事です。 もしこれが出来ない場合は, user-env-compile というラボ機能を使う事が出来ます。しかし、できることなら使用は避けた方が良いでしょう。

Rails3のアセットパイプライン

RailsのアセットパイプラインはHerokuのCedarスタックでサポートされています。新しいパイプラインは、Railsスタックの中でアセットに1級の市民権を与えました。デフォルトで、RailsはJavaScriptを書くためにCoffeeScriptを使用し、CSSを書くためにSCSSを使用します。DHHは彼のRailsカンファレンスでのキーノートの中で素晴らしいイントロダクションをしてくれました。

Railsのアセットパイプラインはアセットをコンパイルし、毎回アプリが起動するたびにコンパイルされるよりも良い、フロントで常にキャッシュされた状態にしておくassets:precompilerakeタスクを提供します。

Herokuでアセットパイプラインを使う方法は3つあります。

  1. ローカルでアセットをコンパイルする。
  2. Slugを作っているときにアセットをコンパイルする。
  3. 実行時にアセットをコンパイルする。

アセットをローカルでコンパイル

`public/assets/manifest.yml`があなたのアプリケーション内にあると、Herokuはあなた自身でアセットのコンパイルを管理すると仮定し、Heroku自身ではアセットをコンパイルしません。

ローカルであなたのアセットをコンパイルするためには、assets:precompileタスクをローカルで、あなたのアプリケーション上で実行してください。プロダクション環境のアセットが生成されるように、production環境を使う事を忘れないでください。

:::term
RAILS_ENV=production bundle exec rake assets:precompile

public/assetsディレクトリが作成されます。このディレクトリの中に、コンパイルされたアセットのmd5sumsが含まれているmanifest.ymlがあると思います。public/assetsをあなたのGitリポジトリにAddする事で、Herokuで利用可能になります。

:::term
git add public/assets
git commit -m "vendor compiled assets"

Pushした時、出力されたメッセージの中に、あなたがローカルでアセットをコンパイルしたことを検知したメッセージがあるはずです :

:::term
-----> Preparing Rails asset pipeline
       Detected manifest.yml, assuming assets were compiled locally

Slug作成時のアセットのコンパイル

アプリケーションの設定変数は、Slugの作成処理中の環境では使う事ができません。なぜならアプリケーションは`assets:precompile`タスクを実行するためにロードされている必要があり、環境変数を要求する初期化コードが`nil`の場合を十分に考慮して制御されなければいけなくなるためです。

もし、ローカルでアセットのコンパイルがガスんでいない場合、私たちはassets:precomplieタスクをSlugの作成中に実行しようとします。あなたのPush時の出力は以下のようになるでしょう :

:::term
-----> Preparing Rails asset pipeline
       Running: rake assets:precompile

私たちのSlugの作成処理にRakeタスクがどのように動くのかという説明がある、下のトラブルシューティングのセクションを確認してください。

実行時のアセットのコンパイル

もし、assets:precompileタスクが失敗したら、実行時のアセットの収集がうまく行かなくなり、出力がそれを示します。

実行時のアセットの収集がうまく動かない場合は、これは最後の手段として使われるべきです。実行時のコンパイルはRailsに対してアセットをDynoの起動時ごとにコンパイルすることを要求し、あたらしいDynoが利用可能になるウェイトタイムを増やすことになります。
:::term
-----> Preparing Rails asset pipeline
       Running: rake assets:precompile
       ERROR: Unable to connect to memcached
       Precompiling assets failed, enabling runtime asset compilation
       Injecting rails31_enable_runtime_asset_compilation

デフォルトでは、Railsはアセットが実行時にコンパイルされることを阻止しようとします。そのため、私たちは実行時のアセットコンパイルを可能にするために、このプラグインを差し込んでいます。

アセットのキャッシュ

静的なアセットのキャッシュは、アプリケーション内でRack::Cacheミドルウェアを使うか、CDNを使ってより分散的な状態で実現をすることができます。あなたのアプリケーションからアセットを提供する事は、Dynoのリソースを要求することになるため、あなたのニーズに合った適切なアセットキャッシュの方法を検討してください。

トラブルシューティング

assets:precompile の失敗

Slugの作成時にassets:procompileが失敗している場合についての修正や対応は、今回ここにはありません。以下で私たちはなぜ動かないのかという理由について見てみたいと思います。

一番一般的なassets:precompileの失敗の原因は、アプリケーションが起動するためにその環境の存在に依存していることにあります。あなたのアプリケーションの設定変数はSlug作成時にその環境に存在していません、そのためあなたは、イニシャライザのなかで設定変数(またアドオン)についてnilの場合を想定してハンドリングするようにステップをふむ必要があります。

もし、以下のようなものを見た場合、 :

:::term
could not connect to server: Connection refused
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port xxxx?

これは、あなたのアプリケーションがrake assets:precompileの一部として、データベースに接続しようとしているところです。なぜなら、設定変数はその環境内で存在していないにもかかわらず、Railsを特定するためにDATABASE_URLプレースホルダを使用しているためです。Slugの作成時に実行する完全なコマンドは以下の通りです :

 env RAILS_ENV=production DATABASE_URL=scheme://user:pass@127.0.0.1/dbname bundle exec rake assets:precompile 2>&1
  • schemeGemfileから転出された適切なデータベースのアダプタに置き換えられます。

アセットをプリコンパイルしている間、Rails 3.xでは、config/applicaiton.rbの中で以下の行をこの通りにすることでデータベースの接続と、初期化処理をしないようにすることができます。

:::term
config.assets.initialize_on_precompile = false

Rails 4.x ではこのオプションは削除され、もう必要ありません。

もし、rake assets:precomileがまだ動いているようであれば、存在していないデータベースをconfig/database.yml内で設定し、rake assets:precompileを実行しようとすることで、ローカルでこれをデバッグすることができます。理想的にはあなたはデータベースに接続することなしで、このコマンドが実行できるようになっているべきです。

therubyracer

もし、以前therubyracertherubyracer-herokuを使っていた場合は、これらのGemがメモリの大部分を消費するため、もう必要となくなり、強く非推奨となりました。

PATHの更新

もし、実行時にアセットをコンパイルする必要がある場合、JavaScriptの実行系にアクセスするため、必ずあなたのPATHにbinを追加してください。heroku configを使って現在のあなたの設定を確認してください :

:::term
$ heroku config
PATH => vendor/bundle/ruby/1.9.1/bin:/usr/local/bin:/usr/bin:/bin

もし、あなたのPATH変数がそれ自身にbinを含んでいない場合は、以下を実行することで更新をしてください :

:::term
$ 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.
Clone this wiki locally