Compressing javascript and css files using PHP

Post Reply
Tony
Lieutenant
Lieutenant
Posts: 86
Joined: Tue Jul 21, 2009 4:11 pm

Compressing javascript and css files using PHP

Post by Tony » Fri Sep 04, 2009 7:23 am

This is a small php code that can be used to compress javascript and css files. It removes all comments and extra spaces from code, reducing its size.

Code: Select all

<?php

function compress_css($file, $urls)
{
    $code = @file_get_contents($file);
    // replace urls
    $code = str_replace('url(' . $urls, 'url(', $code);
    // remove comments
    $code = clean($code, 'css');
   
    return $code;
}

function compress_js($file)
{
    $code = @file_get_contents($file);
    // remove comments
    $code = clean($code, 'js');
   
    return $code;
}


function clean($code, $type)
{
    $start = 0;
    $lines = explode("\n", $code);
    // remove "//" type comments
    for($i=0; $i<count($lines); $i++)
    {
        if(($pos = strpos($lines[$i], '//')) !== false)
        {
            // check if its in string
            $prev = $pos > 0 ? substr($lines[$i], 0, $pos) : '';
            $count = substr_count($prev, "'") - substr_count($prev, "\\'");
            if(($count % 2) == 1) continue;
            $count = substr_count($prev, '"') - substr_count($prev, '\\"');
            if(($count % 2) == 1) continue;
            $lines[$i] = $pos > 0 ? substr($lines[$i], 0, $pos) : '';
        }
    }
    // trim lines
    for($i=0; $i<count($lines); $i++)
    {
        $lines[$i] = trim($lines[$i]);
    }
    $code = implode("\n", $lines);
    // remove /* */ comments
    $start = 0;
    while(($pos = strpos($code, '/*', $start)) !== false)
    {
        $pos2 = strpos($code, '*/', $start);
        $code = substr($code, 0, $pos) . ($pos2 === false ? '' : substr($code, $pos2 + 2));
        $start = $pos2 === false ? strlen($code) : $pos;
    }
    // remove spaces
    if($type == 'js')
    {
        $code = str_replace(array("\t", "\n", "\r", '  '), array(' ', '', '', ' '), $code);
        while(strpos($code, '  ') !== false)
        {
            $code = str_replace('  ', ' ', $code);
        }
    }
    else
    {
        $code = str_replace(array("\t", "\n", "\r", '  '), array(' ', '', '', ' '), $code);
        while(strpos($code, '  ') !== false)
        {
            $code = str_replace('  ', ' ', $code);
        }
    }
    // css stuff
    if($type == 'css')
    {
        $code = str_replace(array('} ', ' }', ' {', '{ ', ': ', '; '), array('}', '}', '{', '{', ':', ';'), $code);
    }
    return $code;
}

?>
Usage is simple:

Code: Select all

<?php
echo compress_css('whatever.css', ''); // reads whatever.css and outputs compressed code
echo compress_js('whatever.js'); // reads whatever.js and outputs compressed code
?>
It might not work with certain files because:
- It isn't designed to handle css hacks that are using comments, such as /*\*//*/
- It removes comments even if they are inside a string, so make sure you don't have strings like str = "/* blah */" (same applies to double spaces and tabs. use "\t" if you want a tab)
- In javascript files make sure you have ; after } where its needed. Example of code that would normally be parsed, but it won't be parsed in compressed format:

Code: Select all

$.fn.whatever = function() { }
$.fn.test = function() {}
 
In that code at the end of both lines ; is missing, but because there is a new line character, javascript parser will parse it anyway. In compressed form all that code is in one line, so you can't skip ; and correct code would be

Code: Select all

$.fn.whatever = function() { };
$.fn.test = function() {};
 
Post Reply

Return to “PHP & MySQL”