Speed up your Apache/Passenger Rails app in 2min
Here’s a quick tip for speeding up your Apache/Passenger powered Rails app. It’ll take you about 2 minutes, and I guarantee you’ll notice the speed-up.
- SSH onto your VPS
- Run the following commands: “a2enmod expires” and “a2enmod deflate”
Now, open up your Apache vhost config for your Rails app. Add the following:
Then, restart Apache by running: “/etc/init.d/apache2 restart”
This will gzip your html, css, and javascript. It’ll also add far future expires headers for the appropriate cacheable filetypes. There’s no downside, and it only takes a second. Bang for buck.
Edit: Check the comments for some possible downsides… ;)
That’ll keep your assets cached forever in browsers and caches. New versions of those files will never be retrieved by clients unless they hard refresh or clear their cache. I’d suggest using Rails-style asset timestamps (“/foo.png?82349824984″) and only set the expires/max-age headers if an asset timestamp is present. Great tip, though. Most sites will see a huge improvement.
Hmm… yeah, I hadn’t thought of the impact on chrome and whatnot. I’ll make a note in the post and reconsider the approach. I’m using the Rails-style asset timestamps, though. Wouldn’t that take care of the cache busting?
I doubt you’re using those asset timestamps in your CSS when referencing images used in the interface. File matching regex should probably be changed to only match if asset timestamp is present, just like Ryan Tomayko said.
Yeah, I guess not. Any chance of getting some pointers on how to fix this?
This would do the trick wouldn’t it:
# gzip html, css and js
AddOutputFilterByType DEFLATE text/html text/css application/x-javascript application/javascript
# far future expires headers
<FilesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)?d{10}$">
ExpiresDefault "access plus 10 years"
</FilesMatch>
Thanks, Josh! I’ll give that a try. Seems like it would work well to me.
Good tip, don’t forget to mention you need to enable mod_deflate also: a2enmod deflate in order for the gzipping to work.
Also, the a2enmod scripts are debian specific i believe? other [lame] distros might need to manually add the module.
And, couldn’t get josh’s code to work, kept saying my css files didn’t have expires headers
After trying a few variations I found I needed to add
ExpiresActive on
to get the Expires headers working. Though I still cannot get the regexp for the timestamps to work. I have tried a few variations that work in Perl/Ruby but I get no results in Apache.
Anyone have a working example that handles timestamps?
Regards
Erik
If this was possible, I think the ‘?’ and ‘d’ in that regex would need to be escaped as follows:
I believe, however, that it will not work. I tried this a number of different ways and it appears that the Apache directive ignores the ‘?’ and everything that follows. Otherwise, how could ‘myimage.jpg?1234567890′ possibly match a regexp ending in “$” (which means string ends here)? I did some tests and this is in fact the case–timestamped assets are matched by the original regex and fail to match with any additions after the file extension.
Oops, comment editor swallowed my example code–must not like angle brackets. My example just added a backslash before the ‘?’ and ‘d’ in the regexp.
[...] two configuartion tweeks are, I believe, the rough equivalent of the technique previously discussed on this blog for [...]
I think you’re right Mike, FilesMatch doesn’t match against the query string.
I’ve been using ERB to render my stylesheets so that they do include time stamps, I wrote about it here: http://deaddeadgood.com/2009/9/28/far-future-expires-headers-for-css-images-in-rails
Using query strings to manage cached assets is unreliable – some caching proxies ignore query strings. Fingerprinted file names is a better solution and recommended by Google. There’s an AssetFingerprint plugin to help with this which I’m shamelessly plugging:
http://blog.eliotsykes.com/2010/05/06/why-rails-asset-caching-is-broken/