Boost Your Web site Performance

In times where web sites behave more and more like web applications, with a constantly growing set of features, most likely developed with JavaScript, it is still of crucial importance that the web site responds to user actions as fast as possible. A couple of months ago, Yahoo! published a set of Exceptional Performance Rules, which – if you adhere to them – can improve the performance of your site significantly. So I had a look how these rules can help me to improve the stats for my own site, www.klauskomenda.com.

Analyzing the present state

Equipped with Firebug and Yahoo!’s YSlow, an extension for Firebug, I first had a look at the current performance measures of this site. Firebug reported the following (under the “Net” tab, select “All”):

Area # requests Datasize (in kB)
Overall: 29 requests, 194kB
HTML 2 31
CSS 5 27
JavaScript 12 84
Images 10 52

YSlow measures a web site’s performance against the abovementioned Exceptional Performance Rules. It grades the performance for every category and finally comes up with an overall performance score for the whole website. The scores for this site were as follows:

# Rule Score Reason
Overall Score: F (45)
1 Make fewer HTTP requests C I had 13 external JS files, 5 external CSS files and 7 CSS background images
2 Use a CDN F Not using a CDN (Content Distribution Network), cause it is just not worth it in my case :-)
3 Add an Expires header F No expires header set for CSS, JS and images
4 Gzip components F No gzipping of HTML, CSS, JS files
5 Put CSS at the top F CSS files were linked with the @import rule, which apparently made them finally load outside of the head
6 Put JS at the bottom A All JS gets loaded at the very bottom of the page, close to the closing body tag. Why?
7 Avoid CSS expressions A No CSS expressions used
8 Make JS and CSS external n/a Not necessary on this website
9 Reduce DNS lookups A Sources only provided by two sources (max.)
10 Minify JS A geolinkr.js file not minified
11 Avoid redirects A No redirects implemented
12 Remove duplicate scripts A No JavaScript file gets included twice in one page
13 Configure ETags F unconfigured on the Apache server

As stated by Jeff Attwood, Yahoo!’s Problems Are Not Your Problems, you need to be careful when following the guidelines for improving your YSlow scores. Some of them are only useful if you run a website with millions of unique visitors per day. If used wrongly, they can even slow down your site. So I took those results, tried to applied as much common sense to them and then tried to improve them using methods described in the following section.

Taking action

1. Reducing HTTP Requests

Even from a not-so-much technical and geeky perspective, this makes sense. If the browser needs to communicate with the server less often, this will make the web site load fast (”less talk, more action”). For me, I have chose two measures to achieve this:

a. through Minification

To reduce the number of HTTP requests for JS and CSS files, I decided to “minify” them into one file each. This not only reduces the number of HTTP requests, but also shrinks the filesize down by removing unnecessary whitespace, comments etc. The minified JavaScript file gets included as close as possible to the closing body tag, the CSS file gets called as soon as possible in the document.

b. by creating CSS Sprites

Of course I see the point in generating CSS Sprites which then contains all (or at least) many of the background-images you use on the site and then position them using CSS properties. I can certainly see the advantages of using a tool like CSS Sprite Generator (done by my co-workers Ed and Stuart) but I decided no to because of the following reasons:

  • YSlow and Firebug are telling me that I am using 7 background images. I think that is not too bad.
  • My background images have mixed formats (JPG, GIF and PNG). Now I could make all of them PNGs and create a CSS Sprite. But I think it does not necessarily make sense, cause you use JPGs for certain images (pictures) and GIFs for images with greater areas of solid colours (e.g. comic illustrations). So mixing all of them into one does not make much sense to me.
  • Most likely, I am doing some little design changes here and there and I certainly don’t want to recreate my CSS Sprite every time.

So I dropped that measure from my list, even though it might mean my score will not increase that much.

2. Adding an Expires Header

To ensure that elements are cacheable I configured Apache in a way that it sets an Expires header for 3 days in the future. This means that before those 3 days are over, the browser will always use the cached version of the image/CSS/JS/HTML file (if there is one). The requirement for this to work is that the mod_expires module is installed on your Apache webserver. You can check for that by doing a phpinfo(). If that is not the case and you don’t have access to the httpd.conf file, you won’t be able to set the Expires Header through Apache. If you do have access to the httpd.conf file, add the following line to the LoadModule section and restart Apache.

LoadModule expires_module modules/mod_expires.so

Now that the module is available you can add the following lines to your .htaccess file:

<IfModule mod_expires.c>
    # enable expirations
    ExpiresActive On

    # sets the Expires date 3 days out from the time of the request
    ExpiresDefault "access plus 3 days"
</IfModule>

Yahoo! recommends to set the Expires header to +10 years after the time of the request. This might be fine for Yahoo!, but this only seems to be wise if you are dead-serious that this file will never ever gonna change. Cause if you do change it on the server, it won’t force any change on the client side…the user agent will not even bother looking for a new version of that file if it is already in the cache. So unless you rename the file, it will never get picked up by the browser until 2017…I mean, unless you clear the cache, of course.

3. Turning on Gzipping

This can be done using the mod_deflate module, which got introduced in Apache with version 2.0. Again, check if that module is available using phpinfo(). The following line in http.conf will load the module:

LoadModule deflate_module modules/mod_deflate.so

The following additions to your .htaccess file will gzip HTML, CSS and JavaScript files:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>

4. Putting CSS at the top of the document

Due to the fact that I used one basic stylesheet and, from within that one, imported the other stylesheets using the @import rule, for some reason, YSlow tells me that those stylesheet are not located in the HEAD section anymore. Because of the fact that the CSS is now minified, there is now only one single request to the CSS file using:

<link rel="stylesheet" href="[path to minified CSS file]" type="text/css" />

5. Configuring ETags…maybe not

As this website does not receive high traffic – and I therefore do not run a serverfarm – and based on Jeff Attwoods article, I decided not to configure ETags at all on the server side. If, for some reason, you would like to do it, you are free to do so by making another addition to your .htaccess file. The following turns off ETags altogether:

FileETag none

Actions taken, measuring again…

After incorporating these changes, I measured the performance again with the same tools mentioned above. The results are:

Area # requests Datasize (in kB)
Overall: 18 requests, 165kB
HTML 1 31
CSS 1 5
JavaScript 6 77
Images 10 52

Here are the noteworthy changes that occured in the YSlow scores including comments as to which scores/rules got affected:

# Rule Score (after) Score (before) Reason/Comments
Overall Score: B (82)
1 Make fewer HTTP requests B C Still 6 JS files and 7 background images
3 Add an Expires header B F Expires header now set, except for external Yahoo! Maps API JavaScript
4 Gzip components A F Now, all components are gzipped
5 Put CSS at the top A F CSS gets now included using link within the HEAD
10 Minify JS A A All JavaScript files get minified
13 Configure ETags F F Left unconfigured

Conclusion

By following the Exceptional Performance Rules (well, rather treating them as guidelines and using them based on Web Development common sense applied to your site/project) I was able to improve the performance of this site as follows:

Area After Before Change
HTTP Requests 18 29 -39%
Page size (in kB) 165 194 -15%
YSlow score B (82) F (45) +37

As you can see, the overall performance scores improved quite significantly. They could even be improved by further reducing the number of HTTP requests (using CSS Sprites) or trying to further minify CSS and JavaScript files. Generally, I feel that the Exceptional Performance Rules are excellent guidelines if you want to improve the performance of any particular site. As stated above, before blindly trying to follow these rules, one needs to verify how valid each of these rules is for the site he or she is working on. The rules were made with websites in mind who serve several million visitors a day – if you own one of those sites, then certainly follow these rules. If not (which is more likely), try to find out which of these rules really make sense in your case.

Further resources