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:
- No file name passed as a parameter
- Unsupported extension
- 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.
Social links and email client: