Difference between Apache and Nginx setup on front-end performance
The first article I wrote for Swipht had to do with front-end performance and I outlined the YSlow rules and how I implemented them on this site.
This blog, as of late March 2009, is powered by Mephisto, a Ruby on Rails-based blog engine. To serve the application, either you pair a front-end web server with an application server, or use Phusion Passenger. I'll explain.
Let's start with Passenger first. Passenger is basically Apache + mod_ruby. It's a lot like mod_php, so you can just upload your files and you're pretty much good to go. This is nice for servers with both PHP and Ruby apps, shared hosting for Ruby, and small sites where there isn't a budget for hosting.
On the other side, there's the paired approach of a front-end web server, like Nginx, LigHTTPD, or Apache with a Ruby application server like Thin, Mongrel or Ebb.
One of the best visual representations of how this works is Heroku's Platform Architecture page. The HTTP Reverse Proxy is our front-end web server. This accepts the initial request from the browser and passes it on to your application server. In a typical setup, there's no HTTP Cache or Routing Mesh. In that diagram, the Dyno Grid acts like a bunch of Thin servers.
Anyway, what does all that have to do with front-end performance? Well, recently we switched from Nginx to Apache and I've been having some problems with the settings. I set up assets.swipht.net as a poor-man's
gzip on; gzip_types text/plain application/xml...; expires max;
YSlow reported A's for both gzipping and expires headers. But, when I switched over to Apache, even though I've set this up before, we lost the expires headers! Gzipping is just as easy, which is the AddOutputFilterByType keyword. Here's part of my virtual host:
#<FilesMatch "\.(gif|jpg|jpeg|png|js|css)$"> # ExpiresDefault "access plus 30 days" #</FilesMatch> ExpiresByType image/gif "access 30 days" ExpiresByType image/jpg "access 30 days" ExpiresByType image/png "access 30 days" ExpiresByType text/css "access 30 days" ExpiresByType text/javascript "access 30 days" ExpiresByType application/x-javascript "access plus 30 days" AddOutputFilterByType DEFLATE text/plain text/html text/css...
You can see the FilesMatch is commented out even though that's what Steve Souders recommends! I then read that the ExpiresDefault might not work as expected, so I tried individual ExpiresByType... none of the files coming from assets.swipht.net now have any expires headers.
Lo and behold... I forgot a declaration! ExpiresActive must be set on On.
ExpiresActive On #<-- don't forget!
<FilesMatch "\.(gif|jpg|jpeg|png|js|css)$">
ExpiresDefault "access plus 30 days"
</FilesMatch>
AddOutputFilterByType DEFLATE text/plain text/html text/css...
That's a lot cleaner! So, the lesson I learned is I need ExpiresActive, and not to forget it in the future.

Post new comment