I’ve talked about how you can speed up your web site by serving less files, now its time to get our hands dirty and see how we can easily combine several files into one.
This will prove to be a very simple but handy addition to your toolkit.
As we are working with several paths for the same file (the physical path and its URL) we need to know the root physical path and URL of your web site, (there is an easy and automatic way to do this) that will be the most tricky situation you will find.
Combining JS files into one is fairly easy, just join then !
Combining several CSS files can be tricky as you might have relative paths in them, so we will replace them with full paths.
Be aware that if you use css to preload images this might break it because the image path will change from img/image.jpg to something like http://www.site.com/path/to/imagef-folder/image.jpg.
Also, the cached file will be served as plain text, with no MIME information so you have to specify an .css extension or your browser wont parse it as being CSS, this could easily be done automatically, but this is just a simple proof of concept.
The code is easy to follow and documented so i will just post typical usage examples but if have any questions about the code just leave a comment
Usage Example 1 : Javascript
$c = new fcDiet('path/to/cache/folder'); $c->webServerPath = 'http://mysite.com/'; $c->physicalPath = '/var/www/html/mysite/' ; $c->addFile('file1.js'); $c->addFile('file2.js'); $c->addFile('file3.js'); $c->addFile('file4.js'); echo '<script type="text/javascript" src="'.$c->get() .'"></script>';
Usage Example 2 : CSS
$c = new fcDiet('path/to/cache/folder'); $c->webServerPath = 'http://mysite.com/'; $c->physicalPath = '/var/www/html/mysite/' ; $c->replacePaths = true; $c->appendExtension('css'); $c->addFile('file1.css'); $c->addFile('file2.css'); $c->addFile('file3.css'); $c->addFile('file4.css'); echo '<link rel="stylesheet" type="text/css" href="'. $c->get().'" />';
The Code
/** * fcDiet * * A simple class to help you join your css and js files into one * * @author Nuno Costa - sven@francodacosta.com * @license GPL */ class fcDiet { public $physicalPath = ''; public $webServerPath = ''; public $replacePaths = false; private $cacheFolder = ''; private $files = null; private $chacheFileName = ''; private $extension = ''; private function createCacheFileName(){ $this->cacheFileName = $this->webServerPath . '/' . $this->cacheFolder. '/' . md5(implode('',$this->files)); if($this->extension != '') $this->cacheFileName .= '.' . $this->extension ; } private function replacePaths($buffer, $path){ $pattern = '/(url\s*)(\(\s*[\"|\']*)([:\/\w\s\d\.]*)([\"|\']*\s*\))/i'; $replace='url(' . str_replace($this->physicalPath, $this->webServerPath, $path) . '$3)'; $ret = preg_replace($pattern, $replace, $buffer); return $ret; } private function cacheHit($file){ return file_exists($file); } function __construct($cacheFolder = ''){ $this->cacheFolder = $cacheFolder ; $this->files = array(); } /** * Adds files to be joined */ function addFile($path){ $this->files[] = $path ; } /** * appends an extension to the cache file * no dot needed just use css instead of .css */ function appendExtension($extension){ $this->extension = $extension; } /** * returns the URL to the cache file * if the cache file does not exits it will be created */ function get(){ $this->createCacheFileName(); $cacheFile = str_replace($this->webServerPath,$this->physicalPath,$this->cacheFileName ); if(! $this->cacheHit($cacheFile)) { $buffer = ''; foreach($this->files as $f){ $tmp = file_get_contents($f) . "\n"; if($this->replacePaths){ //replace url tags with full url $buffer .= $this->replacePaths($tmp, dirname($f).'/'); }else{ $buffer.=$tmp; } } $fh = fopen($cacheFile, 'w'); fputs($fh, $buffer); fclose($fh); } return $this->cacheFileName; } }