Skip to content

rails3x asset pipeline cedar

iwhurtafly edited this page Jul 22, 2012 · 7 revisions

初めに

Bamboo stackでは、Rails 3.1と3.2は、アセットパイプライン無しで実行することが可能でありますが、 これらのバージョンのRailsは、HerokuのCedar stack上で実行するのがベストと言えます。 新規ユーザーの方は、これより先に進む前に、Cedar上にRails 3.xのアプリを作成するチュートリアルを 読むことをオススメします。

アセットパイプライン

Railsの新機能であるアセットパイプラインは、HerokuのCedar stack上でサポートされています。 この新たなパイプラインは、アセットをRailsのスタック内で最優先として扱います。 デフォルトで、RailsはJavaScriptへCoffeeScriptを CSSへSCSSを採用しています。 アセットパイプラインに関しては、DHHが素晴らしいキーノートを RailsConfで行っています。

Railsのアセットパイプラインは、assets:precompileのRakeタスクを実行することで提供されます。 このRakeタスクを実行することで、アセットがコンパイルされ、かつアプリが起動する度にコンパイルを実施するのではなく、 その手前でキャッシュされるよう許可されます。

Herokuでは、アセットパイプラインを使うには、3通りの方法があります。

  1. アセットをローカルでコンパイルする。
  2. slug compilation中にアセットをコンパイルする。
  3. ランタイム中にアセットをコンパイルする。

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

もし、アプリ中に`public/assets/manifest.yml`が検出された場合、Herokuは、アセットのコンパイルを 独自に行おうとしていると判断し、アセットをコンパイルしようとしなくなります。

アセットをローカルでコンパイルするために、アプリ上でassets:precompileタスクを実行して下さい。 本番環境のアセットのバージョンが生成されるようにするために、production環境を使用していることを明確にして下さい。

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

public/assetsディレクトリがクリエートされるでしょう。このディレクトリ内に、コンパイルされたアセットの md5sumsを含んだmanifest.ymlがあります。public/assetsをGitのリポジトリへ追加することで、Herokuでも 利用可能となります。

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

プッシュ時、ローカルでコンパイルされたアセットが検出された旨、表示されます。

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

slug compilation中にアセットをコンパイルする

slug compilationのプロセス中の環境では、アプリの設定変数は利用出来ません。`assets:precompile`タスクを実行するために アプリはロードされている必要があるので、設定変数の存在を必要とするいかなる初期化コードも`nil`ケースを素直にハンドルします。

もし、コンパイルされたアセットをローカルで管理していないのであれば、Herokuでは、slug compilation中に assets:precompileのタスクを実行しようと試みます。プッシュの結果は以下のようになるでしょう。:

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

slug compilationのプロセス中、どのようにRakeタスクが機能するかに関する説明は、 以下にあるトラブルシューティングのセクションを参照して下さい。

ランタイム中にアセットをコンパイルする

もし、assets:precompileタスクが失敗した場合、その結果が画面に表示され、アセットのruntime compilationが 利用可能となります。

アセットのruntime compilationが機能するようになるものの、これは最終手段として使われるべきです。 runtime compilationを使うことは、新たなdynoが利用可能となる待ち時間を増やし、dynoが立ち上がる度に、 Railsがアセットをコンパイルすることを必要とします。
:::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は、ランタイム中にアセットがコンパイルされることを防ぎます。 そこで、アセットのruntime compilationが使えるよう、 我々は、このプラグインを導入しています。

アセットのキャッシュ

静的アセットのキャッシュには、Rack::Cacheのミドルウェアを使い アプリケーション内に実装する方法と、より普及しているCDNにて実装する方法があります。 アプリケーションからアセットを配信することは、dynoのリソースを大幅に必要とします。 そのため、ニーズに合わせて適切なアセットのキャッシュに関するストラテジーを立案して下さい。

トラブルシューティング

assets:precompileの失敗

slug compilation中にassets:precompileが失敗する場合、現在のところ、これに対する修正や回避策はありません。 以下に、今後出くわすであろう共通の問題と機能しない理由について記述して行きます。

assets:precompileの失敗における最も共通の原因は、起動するのに環境を現在形にすることに頼っているアプリ側にあります。 slug compilation中はアプリの設定変数は環境内に存在しないので、イニシャライザの設定変数(それとアドオンのリソース)に対し 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 compilation中に実行されるフルコマンドは次の通りです。:

 env RAILS_ENV=production DATABASE_URL=scheme://user:[email protected]/dbname bundle exec rake assets:precompile 2>&1
  • schemeの箇所は、Gemfileから検出された適切なデータベースアダプターに置き換えられるでしょう。

アセットをプリコンパイルする一方、Rails 3.1.1またはそれ以上のバージョンでは、config/application.rb内に 以下の行を記すことにより、アプリケーションがイニシャライズされることと、データベースへ接続することを防ぐことが出来ます。:

:::term
config.assets.initialize_on_precompile = false

もし、これでもrake assets:precompileが機能しないのであれば、ローカルの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:add 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