Compress your HTML, CSS and Javascript using simple PHP Code

Although Compression is a very important method of making your pages lighter and easier for users to download, it’s definitely going to cost you more CPU and on high load servers it’s not recommended unless you already know how to cache your HTML pages.


GZIP compression
This is highly recommended as it doesn’t need any code and generates Gzipped HTML which almost all today browsers can understand. You need to change/add these values on your php.ini

zlib.output_compression = On
zlib.output_compression_level = 9

you can check the size difference online through http://www.gidnetwork.com/tools/gzip-test.php
read more about Gzip

Javascript and CSS compression
I would firstly recommend taking a look on Dean Edwards ‘s Packer; a JavaScript compressor which could cut your scripts into half size, you might need to download the PHP class that we would be using on the code to compress the JS scripts.

All .js and .css files should be in one folder “js” and all files should be writable by your server including the folder (chmod -R 777 js).
Now you’ll have 2 copies of every JS/CSS file one is readable which you can edit and the other is the compressed file that is included into your HTML using "<script type="text/javascript" language="javascript" src="/js/script.js"></script>" for JS or "<link href="/js/style.css" rel="stylesheet" type="text/css" media="screen" />" for CSS, let’s say our uncompressed files with all the comments and formating is having prefix “local_” before file name then we will always edit that one and dynamically generate the compressed scripts whenever it’s modified.
Here are the functions you need to include

<br />
function JS_check(){<br />
$jsfiles = array('script.js','style.css'); #add names of scripts you like to generate<br />
foreach($jsfiles as $js){<br />
clearstatcache();<br />
#if the file doesn't exist or the time stamp time of both compressed and uncompressed files are not near<br />
if(!file_exists($_SERVER['DOCUMENT_ROOT'].&quot;/js/{$js}&quot;) || ($diff = filemtime($_SERVER['DOCUMENT_ROOT'].&quot;/js/local_{$js}&quot;) - filemtime($_SERVER['DOCUMENT_ROOT'].&quot;/js/{$js}&quot;)) &gt; 3){<br />
if(strpos($js,'.css')===false){ #if a JS file<br />
require_once($_SERVER['DOCUMENT_ROOT'].&quot;/include/class.JavaScriptPacker.php&quot;); #include Packer class<br />
$script = file_get_contents($_SERVER['DOCUMENT_ROOT'].&quot;/js/local_{$js}&quot;); #getting JS file<br />
$script = str_replace(';;;', '//',$script); #the ;;; comment feature in the packer beta
$packer = new JavaScriptPacker($script, 62, 1, 0); #using Dean Edwards 's Packer, check documentations on the class file for the best compression level<br />
$packed = $packer-&gt;pack(); #JS code compressed<br />
}else  #if CSS file<br />
$packed = css_cmpress(file_get_contents($_SERVER['DOCUMENT_ROOT'].&quot;/js/local_{$js}&quot;));<br />
file_put_contents($_SERVER['DOCUMENT_ROOT'].&quot;/js/{$js}&quot;, $packed); #inserting compressed code into files<br />
touch($_SERVER['DOCUMENT_ROOT'].&quot;/js/local_{$js}&quot;); #change the time stamp time for original scripts<br />
#$GLOBALS['debuger'][] = &quot;$js generated, diff was $diff&quot;; #Global array to let you see results<br />
}<br />
}<br />
}<br />
function css_cmpress($css){<br />
$css = preg_replace('!//[^\n\r]+!', '', $css);#comments<br />
$css = preg_replace('/[\r\n\t\s]+/s', ' ', $css);#new lines, multiple spaces/tabs/newlines<br />
$css = preg_replace('#/\*.*?\*/#', '', $css);#comments<br />
$css = preg_replace('/[\s]*([\{\},;:])[\s]*/', '\1', $css);#spaces before and after marks<br />
$css = preg_replace('/^\s+/', '', $css);#spaces on the begining<br />
return $css;<br />
}<br />

HTML compression
although this is not very important and the user might get diffrent results than what you expect but I tried to generate HTML without extra spaces, tabs ,newlines or comments that’s not for IE

function html_compress($html){<br />
preg_match_all('!(&lt;(?:code|pre).*&gt;[^&lt;]+&lt;/(?:code|pre)&gt;)!',$html,$pre);#exclude pre or code tags<br />
$html = preg_replace('!&lt;(?:code|pre).*&gt;[^&lt;]+&lt;/(?:code|pre)&gt;!', '#pre#', $html);#removing all pre or code tags<br />
$html = preg_replace('#&lt;!--[^\[].+--&gt;#', '', $html);#removing HTML comments<br />
$html = preg_replace('/[\r\n\t]+/', ' ', $html);#remove new lines, spaces, tabs<br />
$html = preg_replace('/&gt;[\s]+&lt;/', '&gt;&lt;', $html);#remove new lines, spaces, tabs<br />
$html = preg_replace('/[\s]+/', ' ', $html);#remove new lines, spaces, tabs<br />
if(!empty($pre[0]))<br />
foreach($pre[0] as $tag)<br />
$html = preg_replace('!#pre#!', $tag, $html,1);#putting back pre|code tags<br />
return $html;<br />
}

The only point is that you could enjoy working using formated tags while giving the user exactly what he needs without any extras, remember that you will always have to save all page output into a single variable then echo it which is usually recommended on small pages while could cost you more memory on large pages.

Updated css function, multi-line /**/ comments are now removed

Recommended posts:

  • http://blogulate.com Blogulate

    Great post dude .. worked

  • Pingback: Walid GadElKarim » Blog Archive » Dynamic Content Caching using Lighty + mod_magnet + lua

  • http://notopenyet shawn

    any idea’s on how i can get my front portal page to load faster (graphics and animation from frontpage)

  • http://gadelkareem.com wkarim

    @Shawn
    there are a lot of ways to speed up static contents of your website, check your server’s configuration optimization tutorials for more info. Most common way is to put them on a separate server with a different sub domain like static.gadelkareem.com and use something like lighttpd to serve static contents.

  • http://nophysic.com/ Louis

    Hi wkarim, and thanks for sharing these pieces of code. They are interesting.

    Though I wonder about your html_compress function. Is it necessary to use so much regex ? I have a function that does the nearly the same :

    function compress($string){
    $string = str_replace(“\n”, “”, $string);
    $string = str_replace(“\t”, “”, $string);
    $string = wordwrap($string, 990, “\n”);

    return $string;
    }

    The thing that is cleary missing, is a way to preserve the code and pre tags. So my function is not complete, but yours seems overkill to me.

    There has to be a correct middle.

  • http://gadelkareem.com wkarim

    @louis
    Thanks for your comment.
    I think I need to simplify it a lil yes

  • georgi

    It’a a good idea to pack all files into one
    file for keeping HTTP Requests as low as possible
    (good if you have 5-6 js/css in your page)

  • http://www.atans.cn atans

    multi-line HTML comments are not work

  • http://nix-wie-sparen.de Thomas

    I think you’ll get a lot of Spaghetti code due to this optimization, although it looks very fine.
    I gonna try it on my test-base.
    Thank you!

  • Pingback: semi di marijuana