When YSlow was released to indicate how well a web site performed, there were a lot of people disappointed, and perplexed, by their own score. Overall, I think performance is underrated, so I thought I’d give you some short guidelines how to improve the performance of your web site.
YSlow, for those not familiar with it, is a tool based on the research done by Steve Souders (ex-Yahoo!, now Google) and the Yahoo! performance team, to help people improve web site performance and find common bottle-necks.
The rules and their values
In YSlow, there are 13 rules, which have different values in the overall score, that goes from 0 to 100 (the one rule that has fallen out from the original 14 rules in the High Performance Web Sites book is about AJAX and caching). These are, with respective point values (taken from Dissecting YSlow):
- Rule 5 – Put CSS at the top
- Rule 2 – Use a Content Delivery Network
- Rule 11 – Avoid redirects
What rules to care about
This is where it becomes a little bit more interesting. Most rules everyone agrees about, but there are some that has caused a little bit of a controversy in there. While YSlow: Yahoo’s Problems Are Not Your Problems goes into detail a little bit more, I would argue that the only rule I would definitely want to be optional, and turned off by default, is the Use a Content Delivery Network (CDN) one.
Basically, using a CDN is about having your static content spread out through servers across the world, to offer something as geographically close to your end user as possible, and to meet traffic spikes in the most prepared manner. The fine print here is that CDNs are extremely costly, and the need for one really only applies to enormously high-traffic web sites such as Google, Yahoo! etc.
To force this rule upon us mere mortals with less than one million visitors per day or so is pretty much a waste. CDNs are a good thing, no doubt, but since it only applies to a minority, it should be left out. This means that the best score you can get for a web site is 90/100, so start considering 90 to be top notch/high score.
Some other rules can discussed, but generally, all the rest of them are good ones.
The bases for the following advice is that you have access to two files:
httpd.conf, which is located in your Apache installation folder, and
.htaccess, which is the root of your web site (if it’s not there, just create it).
How to Gzip compontents
Gzipping is the most effective way to compress files, and the way it works is that a web browser states to server that it accepts gzip when it makes a request, and the server then returns the content in a gzipped format. This means that what’s sent over the wire is much, much smaller, thus decreasing bandwidth usage and request time. After the web browser has received the file, it unpacks it and the file works in its original format.
httpd.conf and uncomment this line (for those new to this file, a hash mark (#) is used to comment out a line; just remove it to activate that line):
LoadModule deflate_module libexec/apache2/mod_deflate.so
This approach is rather based on compressing everything, and then specify which file types to exclude from that. Typically, you don’t want to compress images and some other formats, since they are already so compressed to begin with.
SetOutputFilter DEFLATE DeflateFilterNote ratio SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ \ no-gzip dont-vary SetEnvIfNoCase Request_URI \ \.(?:exe|t?gz|zip|bz2|sit|rar)$ \ no-gzip dont-vary SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
Covering up for web browsers which might fail
Naturally, there are web browser out there claiming to support gzip when talking to the server, but not living up to it in practice. Amongst these are Internet Explorer (shocker), at least up till version 6, so you can also add this to the file:
BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0 no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
An alternative way to Gzip
Chances are, your host maybe doesn’t allow you to edit the
httpd.conf file, meaning you can’t rely on Apache to do this for you. However, I found another way to do it through Reducing Bandwidth Usage when Deploying Web Applications. The idea is to locally gzip your files(s), and then name them with a
.gz.css extension, to get the web server and requesting web browsers to treat them as pre-gzipped files.
Open up the Terminal where your files are, and gzip them like this:
gzip -c originalFile > myDeployFile.gz.js
When it comes to the HTML content itself, many tools out there supports compressing it on its own (for you bloggers, WordPress has this under Options > Reading: “WordPress should compress articles (gzip) if browsers ask for them”).
How to configure ETags
ETags are HTTP headers, which identify when a file was changed. The basis is that a web browser will only get that file if the ETag has changed since the last request. There is a very simple way to tell Apache to add an ETag consisting of the file’s modified time and its file size.
Open up the
.htaccess file, add this line, and you’re good to go:
FileETag MTime Size
How to add Expires headers
First, let me explain how requests for a file works:
- If the visitor has an empty cache (in regards to your content), it will fetch all necessary files from the server.
- If the visitor has your files in the web browser cache, it still has to send a conditional GET request to your server, to compare if the last modified time of the file in the web browser cache is the same as the file on the server. If not, it fetches a new version of the file in question.
- If a file has a future expires value set, it won’t even go to the server at all until that time has occurred, thus leading to completely eliminating that request.
Therefore, using expires headers are extremely efficient for static files in your web site. To do it, begin with opening up the
httpd.conf file and enable the expires module:
LoadModule expires_module libexec/apache2/mod_expires.so
Then, open up the
.htaccess file and add what file types you want to set expires header for, and how long that time should be:
Another option can be to turn on expires header for everything:
ExpiresActive On ExpiresDefault "access plus 3 days"
The value needed to get a good YSLow grade is to have expires headers set at least 48 hours into the future, but in practice, you need configure the values that suits your needs the best. Note: If you need to push out new files to the end user and overriding the existing web browser cache, you either have to change the actual file names, or adding a query string to the requests with a new value. For example, changing 19 in the query string below to, e.g. 20, would force the web browser to get a new version from the server.
<link rel=”stylesheet” href=”/css/base.css?19″ type=”text/css”>
We want proof that this works!
Curious and hungry for knowledge, I naturally had to try all this out to improve the end user experience for you, my dear readers. The result of implementing the above solutions are a YSlow ranking for Robert’s talk of (mostly) 80, and for the DOMAssistant web site, a value of 88.
Someone visiting Robert’s talk for the first time will get 30 HTTP requests, while a returning visitor will only have 6 HTTP requests. Quite an improvement, right?
The reasons for not getting 90 (top score unless you’re Donald Trump, remember?) is, for Robert’s talk, my Flickr images and a couple of statistics scripts. With the DOMAssistant web site, it’s only statistics script holding it back from being top notch.
Internet Information Server (IIS)
- IIS 7.0: Configuring HTTP Compression in IIS 7.0
- IIS 7.0: Configure the HTTP Expires Response Header
Django, Apache, and Lighttpd
Also, if you want to read more about what I touched on above, I definitely recommend reading Tools for optimizing your website: Etag and Expire headers in Django, Apache, and Lighttpd.
Performance does matter
At the end of the day, I want you to get good web sites that are incredibly fast to load. Therefore, I sincerely hope you’ve learned something from this that will improve the future performance of the web sites you’ll be working on.
Good luck performing!