Archive for June 21st, 2010
CSS Packer Reloaded
by z3n on Jun.21, 2010, under Coding, Tips & Hints
Sometime ago i posted a simple css packer which basically wipes out the whitespaces, new lines and so on. The javascript packer was also included. Although none of those were 100% my creations i’ve improved the way it works by adding a couple of things:
- Caching based on timestamp on files (aka automatic cache expiry on update)
- Packing multiple files into a single one (ex. if you have 100s of jquery extensions you don’t need to pack them individually, packing everything into a single file is faster and smaller)
- Flexible layout for packing IE specific files
Source:
function css_specifics($fn) {
global $_GET;
if (isset($_GET['q'])) {
return str_replace(".css",".".trim(str_replace(array("..","/"),"",$_GET['q'])).".css",$fn);
} else {
return $fn;
}
}
base_defines(array(
"css_packed" => _is_sadm ? "packed-adm.css" : "packed.css", // css worked file output
"css_include_path" => "css/", // css base include path
"css_cache_path" => "css/cache/", // css cache path
"css_compression" => -1, // css compression method, -1 = disabled
"css_copyright" => "/* (c) z3n - www.overflow.biz - rodrigo.orph@gmail.com */\n\n", // css copyright notice, will appear on packed verisons
"css_debug" => 0,
"css_gzip" => 1
));
$css="";
$_use_cache=0;
$css_packed=css_specifics(css_packed);
$l=(file_exists(css_cache_path.$css_packed)) ? filemtime(css_cache_path.$css_packed) : 0;
if (isset($css_includes) && (!empty($css_includes))) {
if ($l > 0) { // check last mod first
$_use_cache=1;
if (css_debug)
echo "collected includes: ".var_export($css_includes,true)."\n";
foreach ($css_includes as $v) {
$fn=_fn_fix($v{0} == "/" || strpos($v,":\\") !== false || $v{0} == "\\" ? $v : css_include_path.$v);
if (css_debug)
echo "checking lastmod for: ".$v."\n";
if (foo((substr($v,0,5) == "http:") ?
getlastmod($fn)
:
filemtime($fn)
) > $l) {
$_use_cache=0;
break;
}
}
}
if (!$_use_cache) { // re/pack
if (css_debug)
echo "building new cache\n";
// load all js into one
foreach ($css_includes as $v)
$css.=substr($v,0,5) == "http:" ?
file_get_contents($v)."\n"
:
_fs($v{0} == "/" || strpos($v,":\\") !== false || $v{0} == "\\" ? $v : css_include_path.$v)."\n"
;
// @Packager.RemoveLine -> nothing
if (css_debug)
echo "replacing..\n";
// perform basic replaces
$css=str_replace(array(
"##SITE_FULL_URI##"
),array(
site_full_uri
),$css);
// compress
switch (css_compression) {
case "0": // css tidy - http://csstidy.sourceforge.net/
require_once("classes/csstidy/class.csstidy.php");
$x=new csstidy();
$x->set_cfg('preserve_css',true);
$x->set_cfg('remove_last_;',true);
$x->set_cfg('merge_selectors',1);
$x->set_cfg('optimise_shorthands',1);
$x->set_cfg('silent',true);
$x->set_cfg('compress_colors',true);
$x->set_cfg('sort_selectors',false);
$x->set_cfg('sort_properties',false);
$x->set_cfg('discard_invalid_properties',false);
$x->set_cfg('timestamp',false);
$x->load_template("highest_compression");
$x->parse(strip_comments($css));
$css=$x->print->plain();
break;
case "1": // minify - http://www.lateralcode.com/css-minifier/
$css = preg_replace( '#\s+#', ' ', $css );
$css = preg_replace( '#/\*.*?\*/#s', '', $css );
$css = str_replace( '; ', ';', $css );
$css = str_replace( ': ', ':', $css );
$css = str_replace( ' {', '{', $css );
$css = str_replace( '{ ', '{', $css );
$css = str_replace( ', ', ',', $css );
$css = str_replace( '} ', '}', $css );
$css = str_replace( ';}', '}', $css );
break;
default: // no compression/invalid
// nothing!
break;
}
$css=css_copyright.$css; // add copyright notice
if (css_debug)
echo "writing cache..\n";
_fw(css_cache_path.$css_packed,$css,"w"); // save cache
} else { // use cache
if (css_debug)
echo "loading from cache\n";
$css=_fs(css_cache_path.$css_packed);
}
if (css_debug)
echo "output\n - - - \n".$css;
_opt_headers(gmdate(_dt_lm,filemtime(css_cache_path.$css_packed))." GMT"); // check/send 304
header('Content-Type: text/css');
if (css_gzip) // compress
ob_start("ob_gzhandler");
print $css; // final output
}
die;
Usage:
Configure files to be added by:
$css_includes=array(
"file1.css",
"file2.css",
"fileN.css",
"http://www.remote.com/style.css"
);
Do the link by:
<link rel="stylesheet" href="/lib/css.php" type="text/css"> <!--[if IE]><link rel="stylesheet" href="/lib/css.php?q=ie" type="text/css"><![endif]-->
Assuming you have the source into /lib/css.php and, on this case, you have an exception for all IEs.
Notes:
css_include_path = source of css (uncompressed, commented)
css_cache_path = path to save the compressed css
css_compression = method of compression , -1 no compression , 0 = css tidy, 1 = minify
css_debug = enables step by step debug
css_gzip = forces php to output as gzip
Required:
You may also need some functions of my framework, i will post them when i compile a decent common file.