ども、@kimohomです。
先日、以下のHeroku高速化において、asset_syncを利用する方法を紹介した。
Heroku x Rails 使うならオススメの環境構築方法 - ボクココ
ただ、この方法は最近 Heroku 公式から使うのを止めるよう指示が出ている。
Please Do Not Use Asset Sync | Heroku Dev Center
概要をまとめると、
- DRY の原則に反する。 Herokuにあるアセットと、asset_syncでコピーしたs3のアセットの二つができてしまう。
- Syncの最中にデプロイが止まった時などに問題が起きる
とのことだ。代わりに CloudFrontを利用する方法が推奨されている。
AWS CloudFrontとは
簡単にいうと、キャッシュを生成してくれるサーバー。画像URLをCloudFrontに向けておくことで、初めてのリクエストは元のコンテンツ(Origin)を見に行って、CloudFrontにキャッシュとして保存して返す。次回以降は CloudFrontにあるキャッシュを返すことで、高速に画像などを返すことができる仕組みだ。以下の画像がわかりやすい。
Heroku on Rails で CloudFront を利用する
それでは実際のセットアップ方法に移ろう。
まずはCloudFrontにて、Create Distribution を選択。続いて Web の Get Started を選択。
Origin Domain Name
を Herokuに公開しているURLを指定する。独自ドメインを設定してなければ、---.herokuapp.com
となるだろう。他は全部デフォルトでOK。もし何かこだわりがあれば設定を変えていただきたい。これで、CloudFront用のURL(*.cloudfront.net)が生成される。
次に、Rails の config/environments/production.rb
にて、アセットの向き先を変える。
config.action_controller.asset_host = "aaaaaaaaa.cloudfront.net"
基本的にはこれだけで 画像やJS, CSS などがキャッシュされるようになる。
Web フォント を読み込ませる
唯一WebFontを利用する場合は、ちょっとした設定が必要だ。CORS の問題である。 今回はCloudFrontからHerokuに非同期でアクセスできるようにしないといけない。てことで、 Rails 側のCORS設定を変える必要がある。Rack CORSを利用した。
Gemfileにgem 'rack-cors', '0.3.0'
を追加し、bundle install
。
config/application.rb
にて
config.middleware.insert_before 0, "Rack::Cors" do allow do origins '*' resource '*', :headers => 'Content-*', :methods => [:get], :max_age => 0 end end
としてあげる。そんでHerokuにデプロイすれば見事、Webフォントも読み込むようになる。
終わりに
Please Do Not Use Asset Sync | Heroku Dev Centerの記事が公開されたのが執筆時の2週間前、2015/10/28だった。このようにどんどん推奨される方法は変わっていくので、適宜このブログも最新を追って更新していきたい。
Heroku Dev Center は有用な記事が多いので、ぜひチェックしてみていただきたい。
2015/11/30
本件運用してみてCloudFrontが301を返してうまくキャッシュできない現象が多発し、現在調査中である。
heroku - Cloudfront and CSS/JS assets - Stack Overflow
このStackOverflowと事象がかなり近い。何か答えが見つかったらまた報告する。