Page Caching with Dynamic Content in Rails
Posted on Jul 1, 2009 by Charlie Maffitt
I use a lot of page caching to speed up the load time of my Rails apps. I recently ran into a problem, however, where I needed to cache a page which had some dynamic content on it.
Specifically, the page in question was a client’s home page: Because it was the most frequently accessed page on the site, it really needed to be cached. The problem was that there was some dynamic code on the page which determined whether a user was logged in as a site member – If they were, it gave them the options to go to their main account page or to log out. If they were not, it gave them links to log in or to create an account.
That meant that I could not just cache the page as normal, as it would cache whatever version of the dynamic content was first loaded by a user and then display that to all users.
I realized quickly that if I isolated that dynamic content, I could put it in a partial, load the cached version of the HTML, then use Javascript to load the dynamic content from the partial. That way I could still cache the whole page to ease the server load, and only hit the server for what little bit of dynamic content I needed.
Here’s what I did:
The code in my original index view looked like this. The view checks to see if there is a session for the current user and then displays the appropriate navigation:
I pulled the dynamic parts of it out and made a partial in the shared folder, called shared/dynamic_nav.html.erb:
I suppose you could leave the UL tags in the static code, since they don’t really change, but I wanted to keep the partial readable as an entire unordered list, so I moved the whole UL block.
Then I replaced the code in the index page with a call to a javascript function to load the partial after the cached HTML loads:
Then I went into application.js and wrote the following javascript function:
That function makes an AJAX request to a method in the default controller called dynamic_nav:
which loads the partial into the page, generating the necessary code dynamically. If you tail your log and hit the page in your browser, you’ll see that if the page is already cached, you’ll only see the shared/dynamic_nav partial getting rendered in the server log.
Obviously, this isn’t going to speed up page load times as much as a fully cached page would, but it’s still a dramatic improvement over loading the entire page’s code just because you have two little lines of dynamic content.
UPDATE (7/6/2009): Ryan Bates just posted a Railscast covering this same topic, and I encourage you to check it out. He uses a slightly different way of writing the javascript to call the partial, but it’s the same theory – using javascript to render a dynamic partial after the cached static page loads.
Tagged: ruby on rails, page caching, dynamic content, ajax, javascript
Comments
Good work! I have been studying dynamic page caching or content caching for a while and have come across a third party solution that did the trick for me. It is called NWebCache and works quite well under considerable amounts of traffic load. I just wanted to share my experience with your readers so that people who are in need of such a solution can benefit. I know it took me a while to decide. Thanks.
Good work! I have been studying dynamic page caching or content caching for a while and have come across a third party solution that did the trick for me. It is called NWebCache and works quite well under considerable amounts of traffic load. I just wanted to share my experience with your readers so that people who are in need of such a solution can benefit. I know it took me a while to decide. Thanks.