PHP & MySQL, Tutorials

I’ve been looking at my site’s load time in yslow it started out at 78, I’ve been looking at the best way to increase this but in a way that will be easy to maintain.

One way is to merge all your css and js files into a single css/js file this will reduce the number of HTTP requests the browser needs to perform to load up your site. In the past I’ve looked at minify tools with great success, they are very useful but I’ve never managed to use one as part of my workflow. I’ve come up with a solution to add a series of css files and minify them on the fly but whilst keeping the files unminified in storage this means if I ever need to make a change I can do very easily, the browser will receive the minified file containing all the css from my files.

This may not be the best solution but I’ve got great results with it today, raised my site’s score from 78 to 92!

In the header open php and pass and array to a session but also serialize the array so it can be passed as it and then restored back to an array. Since it’s using a session your page will need sessions turned on already.

<?php
//set the css files for the theme
$_SESSION['cssfiles'] = serialize(array(
    'css/bootstrap.css',
    'css/font-awesome/css/font-awesome.css',
    'css/style.css'
));
?>

 Once the array has been passed set the style sheet link to a php file, the file will return all the CSS it needs to be a .php file in order to work, but it will render as CSS.

<link rel="stylesheet" href="css/main.php">

Inside main.php turn on sessions and set an header to render the page as CSS.
Next retrieve the css files from the session and restore it as an array using unserialize, next a function is defined that will remove whitespaced, comment, and tabs, spaces, newlines, etc.

Next inside of a ob_start and loop through the array items, if a css file ends in min.css then it should not be minified again. For each file grab it’s contents.

<?php
session_start();
header('Content-type: text/css; charset: UTF-8');

//collect array from session
$files = unserialize($_SESSION['cssfiles']);

function compress($buffer) {
    /* remove comments */
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
    /* remove tabs, spaces, newlines, etc. */
    $buffer = str_replace(array("\r\n","\r","\n","\t",'  ','    ','     '), '', $buffer);
    /* remove other spaces before/after ; */
    $buffer = preg_replace(array('(( )+{)','({( )+)'), '{', $buffer);
    $buffer = preg_replace(array('(( )+})','(}( )+)','(;( )*})'), '}', $buffer);
    $buffer = preg_replace(array('(;( )+)','(( )+;)'), ';', $buffer);
    return $buffer;
}

ob_start('ob_gzhandler');
    foreach($files as $file) {
        if(strpos(basename($file),'.min.')===false) { //compress files that aren't minified
            ob_start("compress");
               echo file_get_contents($file);
            ob_end_flush();
        } else {
            echo file_get_contents($file);
        }
    }
ob_end_flush();
?>

The result of this is all the contents of the css files will not be in a single file, if the files need to be changed they can be without any further changes needed.

Applying this technique for JS files is virtually the same:

Set the js files in an array and serialize it, store in another session.

<?php
$_SESSION['jsfiles'] = serialize(array(
    'js/jquery.js',
    'js/bootstrap.js',
    'js/scripts.js'
));
?>

Then include the main js file:

<script src="js/main.php"></script>

This main.php file is stored in a js folder.

<?php
session_start();
header('Content-type: text/javascript; charset: UTF-8');

//collect array from session
$files = unserialize($_SESSION['jsfiles']);

ob_start('ob_gzhandler');
    foreach($files as $file) {
        echo file_get_contents($file);
    }
ob_end_flush();
?>

The end result you have a single file for your css scripts and a single file for your js scripts, this also works for cdn scripts, javascript code that you would normally but in style tags say jQuery code etc. I’ve included Twitter and Google scripts that would normally be loaded separately this method means I don’t need separate files to be loaded, reducing the number of HTTP requests.