Railsプロダクションではconfig.assets.compile = trueですが、なぜですか?


185

デフォルトではではインストールアプリRailsのrails new持つconfig.assets.compile = false生産を。

そして、物事を行う通常の方法はrake assets:precompile、アプリをデプロイする前に実行して、すべてのアセットパイプラインアセットが確実にコンパイルされるようにすることです。

ではconfig.assets.compile = true、本番環境に設定するとどうなりますか?

precompileもう走る必要はない。私が信じるのは、アセットが初めてリクエストされたときに、コンパイルされることです。これは初めてのパフォーマンスヒットになります(これを行うには、通常、運用環境でjsランタイムが必要です)。しかし、これらの欠点を除いて、アセットがレイジーコンパイルされた後は、そのアセットへの以降のすべてのアクセスでパフォーマンスヒットは発生しないと思います。アプリのパフォーマンスは、この最初のヒットレイジーコンパイル後のプリコンパイル済みアセットとまったく同じになります。これは本当ですか?

何か足りないものはありますか?config.assets.compile = true本番環境に設定しないその他の理由はありますか?本番環境でJSランタイムを使用していて、実行する必要がない代わりに、アセットへの最初のアクセスでパフォーマンスが低下するというトレードオフを受け入れる意思がある場合precompile、これは理にかなっていますか?


1
警告、古いバージョンのスプロケットにはバグが含まれており、config.assets.compileがtrueに設定されている場合、ディレクトリトラバーサルの脆弱性(blog.heroku.com/rails-asset-pipeline-vulnerability)のリスクがあります
Mauro

これはまさにStackoverflowが機能することになっている方法です。よく書かれた質問とよく書かれた答え。opと@ richard-hulseの両方を愛しています。
schmijos

回答:


259

ガイドのその部分を書きました。

本番環境でライブコンパイルしたくないのは間違いありません。

コンパイルすると、次のようになります。

/ assets内のファイルに対するすべてのリクエストは、Sprocketsに渡されます。すべてのアセットの最初のリクエストで、Railsがキャッシュ(通常はファイルシステム)に使用しているものにコンパイルされ、キャッシュされます。

後続のリクエストでSprocketsはリクエストを受け取り、フィンガープリントされたファイル名を検索する必要があります。アセットを構成するファイル(画像)またはファイル(cssおよびjs)が変更されていないことを確認し、キャッシュされたバージョンがある場合はそれを提供します。

つまり、すべてのフォルダ資産およびプラグインによって使用された特定のベンダー/資産フォルダインチ

正直なところ、コードは速度に合わせて最適化されていないため、これはかなりのオーバーヘッドになります。

これは、アセットがクライアントに送信される速度に影響を与え、サイトのページ読み込み時間に悪影響を及ぼします。

デフォルトと比較してください:

アセットがプリコンパイルされ、コンパイルがオフの場合、アセットはコンパイルされ、にフィンガープリントされますpublic/assets。Sprocketsはプレーンからフィンガープリントされたファイル名のマッピングテーブルをRailsに返し、Railsはこれをファイルシステムに書き込みます。マニフェストファイル(Rails 3のYMLまたはRails 4のランダムな名前のJSON)は、起動時にRailsによってMemoryにロードされ、アセットヘルパーメソッドで使用するためにキャッシュされます。

これにより、正しいフィンガープリントアセットを含むページの生成が非常に高速になり、ファイル自体の提供は、ファイルシステムからのWebサーバーサーバーの高速になります。どちらも、ライブコンパイルよりも劇的に高速です。

パイプラインとフィンガープリントの利点を最大限に活用するには、Webサーバーに遠い将来のヘッダーを設定し、jsファイルとcssファイルのgzip圧縮を有効にする必要があります。Sprocketsは、サーバーが使用するように設定できるgzip圧縮されたバージョンのアセットを書き込み、リクエストごとにそうする必要をなくします。

これにより、可能な限り迅速かつ最小のサイズでアセットがクライアントに送信され、クライアント側のページの表示が高速化され、リクエストが(将来のヘッダーで)削減されます。

したがって、ライブコンパイルの場合は次のようになります。

  1. 非常に遅い
  2. 圧縮不足
  3. ページのレンダリング時間に影響します

  1. できるだけ早く
  2. 圧縮
  3. サーバーから圧縮オーバーヒアを削除します(オプション)。
  4. ページのレンダリング時間を最小限に抑えます。

編集:(フォローアップコメントへの回答)

パイプライン最初のリクエストでプリコンパイルするように変更できますが、そうすることにはいくつかの主要な障害があります。1つ目は、フィンガープリントされた名前のルックアップテーブルが必要であるか、ヘルパーメソッドが遅すぎることです。コンパイルオンデマンドのシナリオでは、新しいアセットがコンパイルまたは要求されるたびにルックアップテーブルに追加する方法が必要になります。

また、誰かがすべてのアセットがコンパイルされて配置されるまでの未知の期間、遅いアセットデリバリーの代償を払わなければならないでしょう。

すべてをコンパイルする代金が一度にオフラインで支払われるデフォルトは、一般の訪問者に影響を与えず、すべてが実際に稼働する前に機能します。

契約違反は、本番システムに多くの複雑さを追加するということです。

[編集、2015年6月]デプロイ中の遅いコンパイル時間の解決策を探しているためにこれを読んでいる場合は、アセットをローカルでプリコンパイルすることを検討してください。これに関する情報は、アセットパイプラインガイドにあります。これにより、変更があった場合にのみローカルでプリコンパイルし、それをコミットして、プリコンパイル段階のない高速展開を行うことができます。


1
ありがとう、私はあなたの答えを受け入れました。しかし、今私の質問は、大丈夫です、今はそれをしませんが、おそらくアセットパイプライン最初のリクエストで遅延コンパイルする機能を持っていると思いますか?指紋マニフェスト?
jrochkind

上記を参照。カピストラーノが機能しないので、これは問題ですか?
Richard Hulse、2012年

カピストラーノは使っていません。私は以前に必要としなかった、追加された複雑さはそれの価値がありませんでした。おそらく、アセットパイプラインは、ラクダを壊してそれを必要とするストローです。あなたの意見では、カピストラーノなどがないアセットパイプラインでRailsデプロイを管理することは不可能ですか?これは残念なことです。簡単なセットアップでは、手作業で行うのはそれほど大きな問題ではありませんでした。
jrochkind、2012

Capistrano for Rails 3.1が本当に必要です。古いアプリの実行中に、アセットが新しいパブリックディレクトリにコンパイルされます。コンパイルが完了すると、新しいバージョンがシンボリックリンクされ、サーバーが自動的に再起動します。
Richard Hulse、2012

「パイプラインとフィンガープリントの利点を最大限に活用するには、Webサーバーで遠い将来のヘッダーを設定し、jsおよびcssファイルのgzip圧縮を有効にする必要があります。この?
Isaac Betesh 2013年

7

プリコンパイルのオーバーヘッドを減らすため。

Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/

次に、画像とスタイルシートを* .html.erbの「/assets/stylesheet.css」または「/assets/web.png」のように使用できます。


6

Herokuを使用しているユーザー向け:

Herkouにデプロイする場合、コンパイルされたアセットが含まれていない(つまりpublic/assetsコミットされていない)場合、デプロイ中に自動的にプリコンパイルが行われるためconfig.assets.compile = true、またはプリコンパイル済みアセットをコミットする必要はありません。

Herokuのドキュメントはこちらです。A CDNは、ダイノリソースの負荷を削除することを推奨します。


1

最初のヒット後でも、プリコンパイルと同じにはなりません。ファイルはファイルシステムに書き込まれないため、Webサーバーから直接提供することはできません。キャッシュエントリを読み取るだけの場合でも、常に一部のルビコードが関与します。


うーん、私はprecompile=trueで、コンパイルされたアセットがファイルシステムに書き込まれると思いました。本気ですか?チェックしてみましょう...
jrochkind

1
ええと、私はあなたが正しいと思います-それらはファイルシステムに書き込まれますが、それはでtmp/cacheはなくのように見えるpublic/assetsので、Webサーバーが見ることができる場所ではなく、それらはまだRailsアプリによって提供されますWebサーバー。何とか。そうだと思いますか?
jrochkind

正しい。Webサーバーに正しくピックアップさせるほど速くはありません。アプリの前にcloudfrontのようなcdnを配置しても問題ないかもしれません
Frederick Cheung

1

セットする config.asset.compile = false

Gemfileに追加

group :assets do gem 'turbo-sprockets-rails3' end

バンドルをインストールする

走る rake assets:precompile

次に、サーバーを起動します


私がconfig.asset.compile = true in production.rbファイルを設定している限り、事前完了メカニズムが追加されていないためです。そのため、サーバーを起動するたびに、ページをロードするのに時間がかかりすぎます(リクエストがリクエストの処理とアセットのコンパイルの両方にヒットした場合)。今私turbo-sprockets-rails3はGemfileにインクルードし、事前にrake assets:precompileアセットをコンパイルするコマンドを実行します。ここでconfig.asset.compile = false in production.rb、サーバーを設定して起動します。ページの読み込みは遅れることはありません。(アセットのコンパイルなしでリクエストのみを処理)
Mohammed Saleem

2
これturbo-sprockets-rails3はRuby 3でのみ必要なことです
Andre Figueiredo

0

公式ガイドから:

最初のリクエストで、アセットは上記の開発で概説したようにコンパイルおよびキャッシュされ、ヘルパーで使用されるマニフェスト名はMD5ハッシュを含むように変更されます。

Sprocketsはまた、Cache-Control HTTPヘッダーをmax-age = 31536000に設定します。これは、サーバーとクライアントブラウザー間のすべてのキャッシュに、このコンテンツ(提供されるファイル)を1年間キャッシュできることを通知します。これにより、サーバーからのこのアセットへのリクエスト数が減少します。アセットはローカルブラウザキャッシュまたは中間キャッシュに存在する可能性が高いです。

このモードは、より多くのメモリを使用し、デフォルトよりもパフォーマンスが低いため、推奨されません。

また、デプロイにCapistranoを使用する場合、プリコンパイルステップはまったく問題ありません。それはあなたのためにそれを世話します。あなたはただ走る

cap deploy

または(設定に応じて)

cap production deploy

これで準備は完了です。それでも使用しない場合は、チェックすることを強くお勧めします。


それで、公式ガイドの言葉が私に同意すると思いますか?私はそのガイドを見ました、それが私が上で提案していることを意味するのかどうかはよくわかりません、どう思いますか?それが私の質問です。
jrochkind

はい、あなたは基本的に同じことを言います。ライブ編集をオンにしないことをお勧めします。
Sergio Tulentsev 2012年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.