Open barmstrong opened 12 years ago
Btw, I tried setting static_cache_control
like this but it didn't seem to have an effect:
# Use a different cache store in production
config.cache_store = :dalli_store
# https://github.com/mattiasottosson/rack-cache-heroku-cedar-example
config.middleware.use Rack::Cache,
:verbose => true,
:metastore => "memcached://#{ENV['MEMCACHE_SERVERS']}",
:entitystore => "memcached://#{ENV['MEMCACHE_SERVERS']}"
config.serve_static_assets = true
config.static_cache_control = "public, max-age=2592000"
Thanks! Glad to hear that you found it useful! This is my first write-up , and I did it while I struggled to learn how http cache works. Felt that I learned it a bit deeper while writing it down, so I thought "why not make an article share it?" :bowtie:
You're correct. The asset pipeline changes the filename on the given asset and applies a hash based on the content of the file. It used to be a query string, like /stylesheets/global.css?1309495796, but that has several disadvantages: http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care
Based on the response, it looks like you're not running your app on the cedar stack?
$ curl -I http://example.com/assets/application-cbc611cbf2c27224a19bd2f1d5923058.css HTTP/1.1 200 OK Server: nginx
It says "Server: niginx", which is not available for the cedar stack. On cedar, all the requests goes directly through the app server (WEBrick by default), so you should see a app server here.
So, if the the app runs on bamboo and the stylesheets are precompiled on deploy, they get written to disk and served directly from nginx without going through the rails stack. Therefore, the static cache control setting doesn't apply and nginx serves the file handles the cache header it self. This applies to the app servers as well, but it happens a "layer back".
The tip/trick is to disable asset precompiling, enable on the fly compiling and gzip together with a cdn, like amazon cloudfront:
curl -I http://d1hedtpacycd9y.cloudfront.net/assets/like_manifest-ad2e08adf6d67d2818455672899c74a4.css HTTP/1.0 200 OK Cache-Control: public, max-age=31536000 Content-Type: text/css Date: Fri, 16 Mar 2012 15:03:18 GMT ETag: "ad2e08adf6d67d2818455672899c74a4" Last-Modified: Fri, 16 Mar 2012 14:49:32 GMT
Here is a really good article on the subject: http://blog.arvidandersson.se/2011/10/03/how-to-do-the-asset-serving-dance-on-heroku-cedar-with-rails-3-1
Oh, two updates btw.
I found that Rack::Cache is enabled in Rails >= 3.1 by default, so you don't need to include it to your Gemfile.
Also found that Dalli also handles the memcache setup, so there is no need to include this:
config.middleware.use Rack::Cache, :verbose => true, :metastore => "memcached://#{ENV['MEMCACHE_SERVERS']}", :entitystore => "memcached://#{ENV['MEMCACHE_SERVERS']}"
It just works right out of the box! :smile:
First, thanks for setting this up! It's very helpful and I've got it up and running on heroku as your described.
One question I have is about the compiled css and js files.
when I curl these I get
It seems like since Rails changes the filename (and hence url) of the static assets on each change, the max-age could be much longer than 3600. Like why not a month or year?
This suggestion comes up when I run my site through Google Page Speed: https://developers.google.com/speed/pagespeed/report
It suggests: "The following cacheable resources have a short freshness lifetime (60 minutes). Specify an expiration at least one week in the future for the following resources:..."
What do you think?