Using Yahoo!’s YSlow: ETags and Compression

January 22, 2009
This entry is part 2 of 2 in the series Speeding Up Web Sites using Yahoo!'s YSlow

In two previous posts, I discussed analyzing my site using Yahoo!’s YSlow Firefox plug-in. I went through the initial test results and the steps I took to improve my score. At the end of part 2, I was left with a grade of 95 (whohoo!) but still two hurdles: ETags and sending compressed JavaScript and CSS.

New to me, and a slightly negative reflection on my site, was entity tags (ETags). An ETag is a unique identifier for a resource. A browser (and other software) can check a resource’s ETag to know whether or not to download the resource, somewhat similar to how expiration headers are used. An ETag can be any value that represents the resource and changes when the resource changes. Commonly the server might use the file’s modification time for this value, or a hash representation of the file as a whole (e.g., run the file’s contents through an MD5 function). My server was providing ETags for all but the main PHP page. This makes sense, because PHP pages aren’t like static HTML pages: my main PHP page is updated whenever the database it uses for its content is updated.

One fix would be to have PHP send an ETag header:

header("ETag: \"representative value\"");

As already written, the representative value could be any of the following:

  • The modification time of the last database record used by the page
  • An MD5 representation of the entire page, including the database-driven content
  • An MD5 representation of just the most recent database record that’s reflected on the page.

And the answer I came up with was…just to ignore ETags on this PHP page. Coming up with any of those values would require a decent rewrite of the entire page, something I just don’t feel like doing right now. And, in my defense, my score turned out pretty well after I addressed the JavaScript and CSS compression issue…

Another reason I lost points was because two of the files being sent (the JavaScript and the CSS) weren’t being compressed. Most of my site uses PHP, which uses the zlib library to compress data sent to the browser. So PHP on the server compacts the HTML, it gets sent to the browser in compressed format, then the browser decompresses it and reads it. That’s great and generally recommended, but the JavaScript and CSS pages aren’t being handled by PHP. One solution is to use Apache’s mod_gzip or mod_deflate module to compress CSS and JavaScript files. To do that, add this code to an .htaccess or .conf file:

<IfModule mod_deflate.c>
<FilesMatch "\.(js|css)$">
SetOutputFilter DEFLATE

That code basically says if mod_deflate is loaded, any file that ends with .js or .css should be ouptut using the deflate filter.

After I took all these steps, I got my YSlow grade up to a 98! I’m pretty pleased with that result. Also, in more concrete terms, if a user accesses my home page for the first time, they perform 4 HTTP requests and download just over 21KB of data. Subsequent requests of that same page require only 1 HTTP request and 3KB of data to be downloaded. That should make a big difference.

To wrap up this thread, I’ll mention two things. First, the YSlow plug-in and report is a very useful tool, but it’s not the only test or indicator of a site’s performance. I do think it’s a great place to start, though. Second, in researching some of these fixes, I came across several other sites where people did the same thing I did (tested their site using YSlow, then tried to address the problems). If you’re interested in this process, you may want to search online to read some of those other articles.

(As a post-script, I will add that one can improve the ETag score by disabling ETags in Apache, strange as this may seem. By doing so, it forces browsers to rely upon the caching headers. So if you can’t or don’t want to get ETags to work, turn them off and they won’t cause a problem.)

As always, thanks for reading and let me know if you have any questions.