Wednesday, 17 July 2013

Improving web performance with Apache and htaccess

Compress content

Compression reduces response times by reducing the size of the HTTP response.
It’s worthwhile to gzip your HTML documents, scripts and stylesheets. In fact, it’s worthwhile to compress any text response including XML and JSON.
Image and PDF files should not be gzipped because they are already compressed. Trying to gzip them not only wastes CPU but can potentially increase file sizes.
To compress your content, Apache 2 comes bundled with the mod_deflate module.
The mod_deflate module provides the DEFLATE output filter that allows output from your server to be compressed before being sent to the client over the network.
Enable gzip compression for text responses:
<ifModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/xml text/css text/plain
  AddOutputFilterByType DEFLATE image/svg+xml application/xhtml+xml application/xml
  AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml
  AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript application/json
  AddOutputFilterByType DEFLATE application/x-font-ttf application/x-font-otf
  AddOutputFilterByType DEFLATE font/truetype font/opentype
</ifModule>

Enable browser cache

Web page designs are getting richer and richer over time, which means more scripts, stylesheets and images in the page. A first-time visitor to your page will make several HTTP requests to download all your sites files, but by using the Expires and Cache-Control headers you make those files cacheable. This avoids unnecessary HTTP requests on subsequent page views.
Apache enables those headers thanks to mod_expires and mod_headers modules.

  1. The mod_expires module controls the setting of the Expires HTTP header and the max-agedirective of the Cache-Control HTTP header in server responses.
  1. To modify Cache-Control directives other than max-age, you can use the mod_headersmodule.
  1. The mod_headers module provides directives to control and modify HTTP request and response headers. Headers can be merged, replaced or removed.

    Rule for setting "Expires" headers:
    # BEGIN Expire headers
    <ifModule mod_expires.c>
      ExpiresActive On
      ExpiresDefault "access plus 5 seconds"
      ExpiresByType image/x-icon "access plus 2592000 seconds"
      ExpiresByType image/jpeg "access plus 2592000 seconds"
      ExpiresByType image/png "access plus 2592000 seconds"
      ExpiresByType image/gif "access plus 2592000 seconds"
      ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
      ExpiresByType text/css "access plus 604800 seconds"
      ExpiresByType text/javascript "access plus 216000 seconds"
      ExpiresByType application/javascript "access plus 216000 seconds"
      ExpiresByType application/x-javascript "access plus 216000 seconds"
      ExpiresByType text/html "access plus 600 seconds"
      ExpiresByType application/xhtml+xml "access plus 600 seconds"
    </ifModule>
    # END Expire headers
    Rule for setting "Cache-Control" headers:
    # BEGIN Cache-Control Headers
    <ifModule mod_headers.c>
      <filesMatch "\.(ico|jpe?g|png|gif|swf)$">
        Header set Cache-Control "public"
      </filesMatch>
      <filesMatch "\.(css)$">
        Header set Cache-Control "public"
      </filesMatch>
      <filesMatch "\.(js)$">
        Header set Cache-Control "private"
      </filesMatch>
      <filesMatch "\.(x?html?|php)$">
        Header set Cache-Control "private, must-revalidate"
      </filesMatch>
    </ifModule>
    # END Cache-Control Headers

    Note 1: There is no need to set max-age directive with Cache-Control header since it is already set by mod_expires module.
    Note 2: must-revalidate means that once a response becomes stale it has to be revalidated; it doesn’t mean that it has to be checked every time.

    Disable HTTP ETag header

    ETags were added to provide a mechanism for validating entities that is more flexible than the last-modified date.
    The problem with ETags is that they typically are constructed using attributes that make them unique to a specific server hosting a site.
    ETags won’t match when a browser gets the original component from one server and later tries to validate that component on a different server.
    In Apache, this is done by simply adding the FileETag directive to your configuration file:
    1
    2
    3
    # BEGIN Turn ETags Off
    FileETag None
    # END Turn ETags Off

    Merge and minify your static files

    Reducing the number of components in turn reduces the number of HTTP requests required to render the page. This is the key to faster pages.
    Minification is the practice of removing unnecessary characters from code to reduce its size thereby improving load times.
    Web performance tools

    Always check your changes. Use either YSlow or Page Speed browser plugins.
    They are super easy to use and the best tools currently available for the job.

    Final file

    Copy the following .htaccess file into the root directory of your site and enjoy the performance improvements.
    # BEGIN Compress text files
    <ifModule mod_deflate.c>
      AddOutputFilterByType DEFLATE text/html text/xml text/css text/plain
      AddOutputFilterByType DEFLATE image/svg+xml application/xhtml+xml application/xml
      AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml
      AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript application/json
      AddOutputFilterByType DEFLATE application/x-font-ttf application/x-font-otf
      AddOutputFilterByType DEFLATE font/truetype font/opentype
    </ifModule>
    # END Compress text files
    # BEGIN Expire headers
    <ifModule mod_expires.c>
      ExpiresActive On
      ExpiresDefault "access plus 5 seconds"
      ExpiresByType image/x-icon "access plus 2592000 seconds"
      ExpiresByType image/jpeg "access plus 2592000 seconds"
      ExpiresByType image/png "access plus 2592000 seconds"
      ExpiresByType image/gif "access plus 2592000 seconds"
      ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
      ExpiresByType text/css "access plus 604800 seconds"
      ExpiresByType text/javascript "access plus 216000 seconds"
      ExpiresByType application/javascript "access plus 216000 seconds"
      ExpiresByType application/x-javascript "access plus 216000 seconds"
      ExpiresByType text/html "access plus 600 seconds"
      ExpiresByType application/xhtml+xml "access plus 600 seconds"
    </ifModule>
    # END Expire headers
    # BEGIN Cache-Control Headers
    <ifModule mod_headers.c>
      <filesMatch "\.(ico|jpe?g|png|gif|swf)$">
        Header set Cache-Control "public"
      </filesMatch>
      <filesMatch "\.(css)$">
        Header set Cache-Control "public"
      </filesMatch>
      <filesMatch "\.(js)$">
        Header set Cache-Control "private"
      </filesMatch>
      <filesMatch "\.(x?html?|php)$">
        Header set Cache-Control "private, must-revalidate"
      </filesMatch>
    </ifModule>
    # END Cache-Control Headers

    # BEGIN Turn ETags Off
    FileETag None
    # END Turn ETags Off

    No comments:

    Post a Comment

    Thank you so much for providing your valuable feedback. I will will look into them and update my skills & technologies accordingly.