samaxes

Icon

Samuel Santos’ ramblings on web development, open source, java technologies, and web standards. Not necessary in that order.

.htaccess - gzip and cache your site for faster loading and bandwidth saving

Last week I changed my hosting provider from Site5 to NearlyFreeSpeech.NET.
Despite the fact that the first one is faster than the second, NFSN is a lot more cheaper (I only pay what I really use).

So in order to speed up my site and save bandwidth (the more I use the more I pay) I use .htaccess file to gzip my text based files and optimize cache HTTP headers.
Although this site is powered by Wordpress which has some really great plugins to optimize PHP output I wanted a more generic solution which can be applied to all PHP web applications.

I also try to follow as much as I can the rules for high performance web sites so don’t be surprised if some Expires header seems too long (far future Expires header rule requires at least 172801 seconds).

Turn on compression

mod_gzip is an external extension module for Apache that allows you to quickly and easily compress your files before you send them to the client. This speeds up your site like crazy!

If your hosting provider has mod_gzip module enabled, the best way to compress your content is to add the following lines to your .htaccess file:

?View Code APACHE
<ifModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

unfortunately my provider doesn’t have this module enabled. If you have the same problem, you can add the following line instead:

?View Code APACHE
php_value output_handler ob_gzhandler

this makes PHP to compress your PHP files (be cautious, this is very CPU intensive).

To compress other static content I use Ali Farhadi’s JSmart Compressor which compress css and javascript files.

Setup JSmart

  • Assuming your application resides in your web root, simply place the JSmart files into /jsmart.
  • Edit /jsmart/config.php if you like, though the default settings should work fine. The mine looks like:
<?php
//JSmart Configuration File
 
//Show error messages if any error occurs (true or false)
define('JSMART_DEBUG_ENABLED', false);
 
//Encoding of your js and css files. (utf-8 or iso-8859-1)
define('JSMART_CHARSET', 'utf-8');
 
//Base dir for javascript files
define('JSMART_JS_DIR', '../');
 
//Base dir for css files
define('JSMART_CSS_DIR', '../');
 
//Change it to false only for debugging purposes
define('JSMART_CACHE_ENABLED', true);
 
//JSmart cache dir
define('JSMART_CACHE_DIR', 'cache/');
?>
  • Create and chmod 777 /jsmart/cache
  • Add the following lines into your .htaccess in your web root:
?View Code APACHE
<ifModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule ^(.*\.(js|css))$ jsmart/load.php?file=$1
</ifModule>

Add future Expires and Cache-Control headers

A first-time visitor to your page will make several HTTP requests to download all your sites files, but using the Expires and Cache-Control headers you make those files cacheable. This avoids unnecessary HTTP requests on subsequent page views.

To set your Expires headers add these lines to your .htaccess:

?View Code APACHE
<ifModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 seconds"
  ExpiresByType text/html "access plus 1 seconds"
  ExpiresByType image/gif "access plus 2592000 seconds"
  ExpiresByType image/jpeg "access plus 2592000 seconds"
  ExpiresByType image/png "access plus 2592000 seconds"
  ExpiresByType text/css "access plus 604800 seconds"
  ExpiresByType text/javascript "access plus 216000 seconds"
  ExpiresByType application/x-javascript "access plus 216000 seconds"
</ifModule>

and to set Cache-Control headers add:

?View Code APACHE
<ifModule mod_headers.c>
  <filesMatch "\\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$">
    Header set Cache-Control "max-age=2592000, public"
  </filesMatch>
  <filesMatch "\\.(css)$">
    Header set Cache-Control "max-age=604800, public"
  </filesMatch>
  <filesMatch "\\.(js)$">
    Header set Cache-Control "max-age=216000, private"
  </filesMatch>
  <filesMatch "\\.(xml|txt)$">
    Header set Cache-Control "max-age=216000, public, must-revalidate"
  </filesMatch>
  <filesMatch "\\.(html|htm|php)$">
    Header set Cache-Control "max-age=1, private, must-revalidate"
  </filesMatch>
</ifModule>

Now all your files must have the right headers and be cacheable except the css and javascript files processed by JSmart. This is because JSmart overrides the cache headers when gzipping these files.

To fix this you have to edit /jsmart/load.php file and change the block code

if (JSMART_CACHE_ENABLED) {
  if (isset($headers['If-Modified-Since']) && $headers['If-Modified-Since'] == $mtimestr)
    header_exit('304 Not Modified');
 
  header("Last-Modified: " . $mtimestr);
  header("Cache-Control: must-revalidate", false);
} else header_nocache();

to

if (JSMART_CACHE_ENABLED) {
  if (isset($headers['If-Modified-Since']) && $headers['If-Modified-Since'] == $mtimestr)
    header_exit('304 Not Modified');
 
  if ($file_type=='js') {
    header("Expires: " . gmdate("D, d M Y H:i:s", $mtime + 216000) . " GMT");
    header("Cache-Control: max-age=216000, private, must-revalidate", true);
  } else {
    header("Expires: " . gmdate("D, d M Y H:i:s", $mtime + 604800) . " GMT");
    header("Cache-Control: max-age=604800, public, must-revalidate", true);
  }
} else header_nocache();

Turn off ETags

By removing the ETag header, you disable caches and browsers from being able to validate files, so they are forced to rely on your Cache-Control and Expires header.
Entity tags (ETags) are a mechanism to check for a newer version of a cached file.

Add these lines to .htaccess:

?View Code APACHE
<ifModule mod_headers.c>
  Header unset ETag
</ifModule>
FileETag None

Remove Last-Modified header

If you remove the Last-Modified and ETag header, you will totally eliminate If-Modified-Since and If-None-Match requests and their 304 Not Modified responses, so a file will stay cached without checking for updates until the Expires header indicates new content is available!

Add these lines to .htaccess:

?View Code APACHE
<ifModule mod_headers.c>
  Header unset Last-Modified
</ifModule>

Notes

With these settings you should have your site a lot faster and your file’s size greatly reduced.

Resources

Some descriptions are based on .htaccess (Hypertext Access) Articles from AskApache.
mod_gzip settings are taken from Highub - Web Development Blog.

Bookmark and Share

Related Posts

22 Responses

  1. AskApache says:

    Excellent article! Very nice, you’ll need the faster speed these tips provide when I start sending traffic your way. You might also like: Hacking wp-cache for ultimate speed.
    ;)
    AskApache

  2. Thanks. I’m waiting for it :)

  3. [...] .htaccess - gzip and cache your site for faster loading and bandwidth saving [...]

  4. [...] .htaccess - gzip and cache your site for faster loading and bandwidth saving (tags: apache) [...]

  5. Alex says:

    thanks.
    i search this tool and this works fine.

    tipp:
    use htaccess for rewriting the urls. it’s better for the security and static files look like nicer

  6. George says:

    Thanks for the great article…. I was using mod_expires and gzip only. I just added the eTag, mod_headers stuff to my htaccess … hope it gives my sites a boost in speed.

    Thanks again.
    Stumbled it !

  7. Kelvin says:

    Undeniable, a must read & practice for all webmaster!
    Thanks for the tips!

  8. Greg Brown says:

    Nice article - my only question is should you be gzipping your jpg/png/gif files? They’re already compressed so I’d have thought gzipping wouldn’t noticeably reduce the file size, and just create unnecessary processor overhead.

  9. Yes Greg, you are right. jpg/png/gif files shouldn’t be gzipped.

    The mod_gzip configuration has been updated. Thanks!

  10. Nidia says:

    Wow!!
    What a G R E A T tip!!!
    My site is now very very fast!!

  11. [...] faster loading and bandwidth saving Posted October 13, 2008 Filed under: Uncategorized | samaxes » .htaccess - gzip and cache your site for faster loading and bandwidth saving .htaccess - gzip and cache your site for faster loading and bandwidth [...]

  12. [...] Great .htaccess discussion. [...]

  13. fakhru says:

    Nice article it help me a lot to speed up my site
    thanks a lot

  14. William says:

    Thank you, I was about to dump Wordpress and my host to do speed issues, but thanks to these tips, my site now runs faster than before!

  15. -= Cara =- says:

    Thank you very much for tips and tricks!

  16. Mike says:

    Thank you for this overview of different methods.

    I was especially happy with Smart Optimizer, thank you so much for mentioning it!

    I saved 36% in total :)

  17. JAB_au says:

    Thanks for the guide, I was using PHP GZip method on my site (WWN) before this, the .htaccess method was something I didn’t know.

    Thanks.

  18. KnyghtMare says:

    If your host is up-to-date you won’t have mod_gzip becaues it was renamed/morphed into mod_deflate

  19. mod_gzip still exists as an external extension module and mod_deflate only comes bundle with Apache since the version 2.
    Unfortunately for me, my host still uses Apache 1.3.

  20. [...] gzip 压缩减少页面加载时间的 .htaccess 技巧,文章太长,请点击 .htaccess-gazip and cache your site for faster loading and bandwidth saving [...]

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Sponsors