This blog is part of our Rails 5 series.
Rails 5 allows to cache HTTP responses forever by introducing http_cache_forever method.
Sometimes, we have static pages that never/rarely change.
1 2# app/controllers/home_controller.rb 3class HomeController < ApplicationController 4 def index 5 render 6 end 7end 8 9# app/views/home/index.html.erb 10<h1>Welcome</h1> 11
Let's see log for the above action.
1 2Processing by HomeController#index as HTML 3 Rendered home/index.html.erb within layouts/application (1.3ms) 4Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms) 5 6 And so on for every request for this action.
There is no change in the response and still we are rendering same thing again and again and again.
Rails 5 introduces http_cache_forever
When response does not change then we want browsers and proxies to cache it for a long time.
Method http_cache_forever allows us to set response headers to tell browsers and proxies that response has not modified.
1 2# app/controllers/home_controller.rb 3class HomeController < ApplicationController 4 def index 5 http_cache_forever(public: true) {} 6 end 7end 8 9# OR 10class HomeController < ApplicationController 11 def index 12 http_cache_forever(public: true) do 13 render 14 end 15 end 16end 17 18 19# app/views/home/index.html.erb 20<h1>Welcome</h1> 21
Now let's look at the log for the modified code.
1 2# When request is made for the first time. 3 4Processing by HomeController#index as HTML 5 Rendered home/index.html.erb within layouts/application (1.3ms) 6Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms) 7 8# For consecutive requests for the same page 9 10Processing by HomeController#index as HTML 11Completed 304 Not Modified in 2ms (ActiveRecord: 0.0ms) 12
On first hit, we serve the request normally but, then on each subsequent request cache is revalidated and a "304 Not Modified" response is sent to the browser.
Options with http_cache_forever
By default, HTTP responses are cached only on the user's web browser. To allow proxies to cache the response, we can set public to true to indicate that they can serve the cached response.
Use http_cache_forever with caution
By using this method, Cache-Control: max-age=3155760000 is set as response header and browser/proxy won't revalidate the resource back to the server unless force reload is done.
In case force reload is done, Cache-Control: max-age=0 is set as request header.
In this case, browser will receive the changed resource whether ETag is changed or not.
http_cache_forever is literally going to set the headers to cache it for 100 years and developers would have to take extra steps to revalidate it. So, this should be used with extra care.