ボクココ

個人開発に関するテックブログ

Heroku on Rails で asset_sync ではなく Cloudfront を利用する方法

ども、@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と事象がかなり近い。何か答えが見つかったらまた報告する。