ENV['RAILS_ASSET_ID'] - The Silent Killer
I discovered this issue after working with rails for less than a month, but after various conversations I’ve had with various people, I think it’s important that I share this tip so that everyone can benefit from it.
Default Behavior with Perverse Side Effects
Rails default behavior has this set to nil, which is a serious performance issue on many levels if you have any traffic your site at all. Even if you have the servers and/or bandwidth to handle it, some of your users will see your site just crawl and crawl…
If you haven’t set to a constant value (or maybe your app revision?), then set to an empty string in your environment.rb, or you’ll be sorry:
My Recommended Solution
ENV["RAILS_ASSET_ID"] = '' # Prevents numerous file stat() calls
# and client-side cache busting.
Why do we want to buck the trend?
Seriously, though, when I took the lead on the development of CollectiveX I happened to take a look at the static asset paths that rails was generating by default, and I was shocked to say the least:
# Example image path w/ default settings.
/images/icons/someicon.gif?123456789
Cache Busting Paths… by Default?!?
While this may reduce the bug reports that the rails core developers get from newbies that don’t realize that their images are being cached in the browser, it makes your app behave in a shocking manner which is nowhere near sufficiently documented.
Tens or Hundreds of File Stats on Each Request
If ENV['RAILS_ASSET_ID'] is unset or nil, then Rails will stat the target file to determine it’s mtime.
This will happen for every single static asset on your page, and every time the page is rendered.
URLs which prohibit HTTP caching by nature
Next, when the browser retrieves your page, it is actually prohibited from caching any of the images, by the HTTP spec, due to the GET parameter in the query string portion of the URL.
Some browsers will disobey this part of the spec, others will not.
This is the exact same technique recommended to users having issues with Internet Explorer caching their AJAX responses. This is a cache busting technique.
What You Should be Doing Instead
- Turn off the asset ID:
ENV["RAILS_ASSET_ID"] = '' # In your environment.rb
- Set caching directives in your webserver’s configuration files.
- Use an asset packager:
Asset Packager
We use a heavily modified version at CollectiveX, which I’ll post here soon
Bundle-Fu
Never tried it
- Use more aggressive caching directives for assets which are packaged. Now you control when the client-side cache gets busted, because the URL changes only when the revision has changed.
If You’re Still Not Sure What This is All About
Just ask me, I won’t mind. :)