Access options:

Gzip content to speed up your site

author: mike foskett updated: 25th September 2008

Serving compressed pages reduces the size of the page by 50% to 70%, the larger the file the better the benefit.

Presented here is a small PHP program for serving gzipped static content to a browser. Most useful for stylesheets, javascript and html. May be extended to use with any static content such as text or xml.

Download gzip_content.zip [1.14 KB].

How to use it

For this example we'll work on a CSS file, though it works for any static file.

Folder structure

Place index.php in the CSS folder.

Pre-compress a css file and place it in the same folder. I personally use 7-zip a free, open-source, compression tool which also supports the most commonly compressed formats.

The folder should look something like:


/css/
      page.css
      page.css.gz
      index.php

In your XHTML

Use the @import method to attach style sheets it is actually quicker than the link alternative:


<style type="text/css">@import "/css/index.php?file=page.css";</style>

I prefer to reference the folder with just the query. index.php should run as default:


<style type="text/css">@import "/css/?file=page.css";</style>

If your server is running Apache then a better method is to add a rewrite rule to a .htaccess file and place in the CSS folder.

The following rewrite rule will redirect all calls for a file /css/*.css to /css/index.php?file=*.css.


RewriteEngine on
RewriteBase /
RewriteRule ^(.*\.css) index.php?file=$1

The XHTML can now be rewritten as:


<style type="text/css">@import "/css/page.css";</style>

How it works

Firstly a check is done on the parameter passed in the url. Any errors generate a friendly error message

Then it checks gzip content is acceptable to the browser. If not it serves an uncompressed version of the content.

It then looks for an existing pre-compressed gzip file and, if available, serves that.

Failing that it takes the uncompressed file and compresses it on-the-fly.

Check parameters

Check that a file name is passed into the program and that it's a supported type. Extensions supported are: .html, .css and .js.


<?php
$filename=$HTTP_GET_VARS["file"];
$exts = array('js','css','html');
if (!$filename){errorExit('No filename passed.'.dirList());}

$ext = substr(strrchr($filename,'.'),1);
switch ($ext){
case 'js':
    header('Content-Type: text/javascript; charset=UTF-8');
    break;
case 'css':
    header('Content-Type: text/css; charset=UTF-8');
    break;
case 'html':
    header('Content-Type: text/html; charset=UTF-8');
    break;
default:
    errorExit("Unsupported file extension:\n        ".$filename.extList());
    break;
}

Check gzip content is acceptable to the browser

When a browser requests a file it also states what types are acceptable:


// Check browser accepts gzipped content
$gzip = in_array('gzip', array_map('trim', explode(',' , @$_SERVER['HTTP_ACCEPT_ENCODING'])));
if ($gzip) {
  header("Content-Encoding: gzip");

  // look for pre-existing gzip file
  if (file_exists($filename.'.gz')){
    $filename.='.gz';
  }else{
    // gzip content on-the-fly
    ob_start("ob_gzhandler");
  }
}
if (!file_exists($filename)){errorExit('Non existant file: '.$filename.dirList());}

Add a far-future header

A far futures header will tell the browser to keep a copy in it's cache.


  // add a far future header before serving
  header("Expires: " . gmdatestr(time() + 315360000));
  header("Cache-Control: max-age=315360000");
  header("Content-Length: ".filesize($filename));
  readfile($filename);
  die;

  // get today's time and date
  function gmdatestr($time = null) {
    if (is_null($time)) $time = time();
    return gmdate("D, d M Y H:i:s", $time) . " GMT";
  }

Report any errors incurred

For debugging purposes there are three detected errors:

  1. No file name passed as a parameter
  2. Unsupported extension
  3. File does not exist on the server

  function errorExit($msg){
    header('Content-Type: text/html; charset=UTF-8');
    header("Content-Encoding: none");
    echo "<script type=\"text/javascript\">\n";
    echo "alert('Error: ".str_replace("\n", "\\n", addslashes($msg))."');\n";
    echo "</script>\n";
    exit();
  }

  // returns a list of valid files
  function dirList(){
    global $exts;
    $str="";
    $dir = opendir(".");
    while($entry = readdir($dir)){
      if (in_array(substr(strrchr($entry,'.'),1), $exts)){
        $str.="        ".$entry."\n";
      }
    }
    closedir($dir);
    if ($str){
      $str="\n\nValid files present:\n".$str;
    }else{
      $str="\n\nNo valid files present\n";
    }
    return $str;
  }

  // returns a list of valid extensions
  function extList(){
    global $exts;
    $str="\n\nSupported extensions:\n".
    foreach ($exts as $value){
      $str.="       .".$value."\n";
    }
    return $str;
  }
}
?>

Going further with compression techniques

This resource is aimed at those getting started with file compression and speed optimisation. There are better, albeit more complex, methods available. Take a look through the resources for further reading.

Site search & complementary navigation:

Site search:

Online tools

Related articles

Related books

Related CSS

Related tools

New to site

Most popular

Inspect report: