Improve Your YSlow Grade Using .htaccess
This post was authored by Eric Wendelin. To learn more about Eric, click here.
A significant part of your YSlow grade depends on how well your site utilizes optimal caching techniques. By editing your .htaccess file, you can increase your YSlow score by 20 points or so in just 3 minutes!
Quick Intro to Caching
Caching is a browser feature that allows storage of certain types of web files on the client-side. In most cases, we want to have our clients cache our static files like HTML and CSS so that our website is faster after the first request.
Browser caching mainly depends on two things: the headers you send in an HTTP response and the browser your client is using.
There are a couple of things a browser can do when caching depending on the headers used.
- It can check back on every request, and servers will reply with a HTTP status 304 (Not Modified) if the file is indeed the same.
- Only ask the server for the file when the cached one has expired.
The latter case is better for performance because the browser doesn't even ask and therefore saves a lot of HTTP requests.
Setting the Expires Header
One of the best things we can do to ensure good cache-ability is set a far future Expires header:
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)(\.gz)?$"> Header set Expires "Thu, 15 Apr 2012 20:00:00 GMT" </FilesMatch>
Note here that if your site changes a lot, you'll need to rename/version your files or get clever with your ETags to keep users up-to-date. If you Firebug my site, eriwen.com, you'll see that I do just that. Stay tuned there for a script that can help you automate this.
Controlling Those ETags
ETags are difficult because they take precedence for caching in most browsers. You can change all the headers you want, but if the ETag associated with a file is always the same, caching will never work how you expect. In most situations, you should turn your ETag headers off.
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)(\.gz)?$"> Header unset ETag FileETag None </FilesMatch>
Yes, you can combine the two snippets:
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)(\.gz)?$"> Header set Expires "Thu, 15 Apr 2012 20:00:00 GMT" Header unset ETag FileETag None </FilesMatch>
Testing Your New Settings
The best way to see what's going on is to check the "Net" tab in Firebug. You can use a tool like the Live HTTP Headers Firefox extension (there's also one for IE) to verify what headers are being sent. NOTE: If you refresh the page instead of clicking a link, Firefox will recheck all files it has cached. This is not the test you're looking for.
You want to make sure everything is occurring exactly as you intended. Now is the time to bring out your inner control-freak.
Conclusion
These are just 2 simple ways to maximize caching (and therefore speed) of your site. There are lots of other headers to play with, but I find that these two give the biggest bang for your buck. Share your caching tricks in the comments!
About Eric Wendelin
Eric Wendelin is a software engineer for Sun Microsystems. When he’s not doing super-secret programming for Sun, he plays indoor soccer, playing Wii with his friends, and cheering on the Colorado Avalanche. He also writes a blog on JavaScript, CSS, Java, and Productivity at eriwen.com
Thank you for hosting such a good article, Dave, another thing difficult to find a tutorial around is about gzipping resources (js, css) …any hint about this topic?
I have googled around but nothing good came out: did you successfully try to gzip the site resources or do you know a good article about this?
Thanks for your interesting work though!
Stefano
@Stefano: Yes, GZipping is the last step here.
Here are a few lines from my .htaccess that WOULD do this if my hosting provider let me :(
I have added this in my htaccess file.
@Stefano: Yes, Gzipping is the last step here.
I tried to post code for it, but it was eaten by David’s spam protector :(
My hosting provider doesn’t allow Gzipping so you might check with yours if you’re unsuccessful.
Interesting article, I didn’t know ETags issues at all! I’ll take a look to gzipping too.
Thx Dave and Eric.
Wow I didn’t even know there was two types of caching! Cool article Eric!
@eric
it is not advised to deflate binary content like images
Technique works nice. Thanks!
Websitewent from a 51 score to 74 points
@xrado: Good note. If anyone uses my GZip stuff above remove the binary extensions like jpg, png, etc.
@Monkeytail: There you go! Nice!
My blog’s speed has improved a lot from this script. Thanks Eric!
thank you very much for that!
but i work with a lot with dynamic generated images (ie. .png?scale=200×400)
so i modified your regex to match also uri’s with parameters:
\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)(\.gz)?(\?.*)?$
HTH
@Michael:
You’re entering the asteroid field there. It’s uncharted. IIRC IE will never cache anything with a query string. I can’t say for certain what FF or the others will do. If you know more about this I’d love to hear it!
This is my .htaccess snippet that I use on all my sites that run on servers that support it:
################ Expires Control ################
ExpiresActive On
ExpiresDefault A0
<FilesMatch “\.(gif|jpg|jpeg|png|swf)$”>
# 2 weeks
ExpiresDefault A1209600
Header append Cache-Control “public”
</FilesMatch>
<FilesMatch “\.(xml|txt|html)$”>
# 2 hours
ExpiresDefault A7200
Header append Cache-Control “proxy-revalidate”
</FilesMatch>
<FilesMatch “\.(js|css)$”>
# 3 days
ExpiresDefault A259200
Header append Cache-Control “proxy-revalidate”
</FilesMatch>
If i paste the code given here on my .htaccess file i get a 500 error after refreshing
Hello Makis
When you copy and paste the code form Here your code is getting changed specially for the closing double quotation. In respect with all replies regarding how to fix your web server and running HTTP server are wrong.
Try to replace the “…” start and end double quotation with your hand and it will work. because when you copy and paste it it turned to ؛؛…؛؛ and you cannot notice that.
@Makis: Your server may not have some of the functionalities above enabled or installed.
@Makis: David is right. I’m sure you’ve double-checked that everything was copied perfectly, too. Some hosts might not allow this functionality
Thanx for the fast replies.
I m on a dedi server so i can change whatever is possible.
Do you know how can i enable these functions?
Thank you once more!
@Makis: Which HTTP server are you running?
Hi Eric!
I m using Apache: 2.2.9
@Makis:
Try adding or un-commenting this in your httpd.conf file:
LoadModule headers_module modules/mod_headers.so
AccessFileName .htaccess
Hope that helps :)
@Makis:
Try adding or un-commenting this in your httpd.conf file:
LoadModule headers_module modules/mod_headers.so
AccessFileName .htaccess
Hi Eric,
i’ve seen with YSlow that you are able to deflate “js” file with parameter (eg. http://davidwalsh.name/wp-includes/js/tw-sack.js?ver=1.6.1). On my dev site i can do this only with js without parameter. As soon as i have a parameter with my javascript file the deflate compression doesn’t works :( .
I use this syntax (but i’ve tried too, the code from Michael without any success)
<IfModule mod_deflate.c>
<FilesMatch “\.(js|css|htm|html|pdf)$”>
SetOutputFilter DEFLATE
</FilesMatch>
</IfModule>
Could you help me with that weird problem ?
TIA,
Pierre.
Good article..
So, what do we do when we setup caching methods like this (e.g. for images) and you replace an image (jpg) on a website with a newer version (let’s say a better cropped one for example). Do I have to wait 2 weeks (if I set ExpireDate to that) before I see the new picture on the site, or can I somehow force the browser of the client to d/l the new version (even without adding a @timestamp to the image src=”” in the code)…?
Versioning js/css files seems like an option, though a lot of work (renaming, updating files that include the versioned file, etc.).. but they do change a lot for projects usually.
Rolf
Ok, i found by myself…
It’s because i use GoogleGears so YSlow was a little missed :).
Thanks anyway
Amicably,
Pierre
@Rolf: In your case I think it’s best to rename the file.
I’ve posted this with improvements for gzipping and cache-control to GitHub: http://gist.github.com/188105
I have a question:
Setting off Etags is going to affect the grade on the “Configure entity tags (ETags)” category on Yslow?
@kasap: Yes. ETags being off will improve your YSlow score. ETags should be turned off unless you really know how to use them.
Great optimization tip. I’m going to try it straight away.
Thanks Eric.
Hi,
The code for .htaccess contains – Header set Expires “Thu, 15 Apr 2012 20:00:00 GMT” which means that all the images will expire on 15th April 2012 at 20:00:00 .
But how can i change the expire date to something like the cache shud become stale always after 14days. i mean i want to implement something like this ->
How can i do this?
One more thing, setting Expires is enough, or we also need to set Cache-Control, becoz Expires is something related to HTTP/1.0 and Cache-Control is related to HTTP/1.1
Thank You,
Dave
Thanks for this nice article. – I improved my Yslow Grade with your tipps!
Many thanks from Germany.
Michael
Thanks very much for giving such a great detail..!!
I’m really impressed by this way..!!
It reduces load time of my site really up-too great extent..!!
Thanks..!!
These snippets seem to be worth placing on the sites but I am so new to this I haven’t any ides of where they would be placed, sounds dumb ha, tell me where would they go and how to be placed.
My blog loading speed has increased, thank you very much.
thanks for the info. It moved my grade up 1 point, but everything helps.
After going over a number of the articles on your blog, I really like your technique of blogging.
I book marked it to my bookmark website list and will be checking back
in the near future. Take a look at my web site too and tell me how you feel.
This perhaps could make a VERY SMALL difference.
You need to min all your JS and put it in the footer. Min all your CSS and put it in the header
Make sure your site is gzipped.
You do those 3 things and your actually going to see a difference. For example this blog has 28 JS files in the head of the document tsk tsk tsk
thank you so much for the nice explanation,
Why using W3TC my test results are still F
Whereas the existing htaccess settings similar to those you share
One more thing, setting Expires is enough, or we also need to set Cache-Control, becoz Expires is something related to HTTP/1.0 and Cache-Control is related to HTTP/1.1
Getting error on yslow that “Add Expires headers”. How can i add for external urls?
Thanks for the summary. These tips work exceptionally well for a Magento installation. We implemented these tweaks recently and saw a nice boost in speed.
I have used the code to disable
ETag
, but does not functionHope this helps!
After read this, my speedtest result show C. Thanks
Increase page loading speed
I’ve tried several variations of updating my ETags, but when I check my Yslow grade it doesn’t change. I did go from a D to a C initially, but I seem to be at a stand still now. Just curious if anyone else is running into the same issue.