Combine & Minify Assets with Lithium
li3_assets is a nice Lithium library that I've been working on for the Lithium php framework. It is a very easy to configure (and use) library that will combine and optimize your assets all into one file. How does this impact your web site? Well really, it's how traffic won't impact your web server. What happens is instead of say 5 or 6 JavaScript files if you're using jQuery and a handful of plugins, you'll have just one and it will be minified or packed for you. So you don't even need to be using a minified or packed version of the script. In my test here, I saw 12 requests go down to 5 requests and 302Kb page size drop to 187Kb. The numbers really can be staggering depending on how many scripts (and css files) and whether or not they were originally minified or packed or not. This helps overall performance in a website and helps when you have large amounts of traffic coming to your website. The server will serve out less requests and smaller amounts of data so it can handle more visitors.
For JavaScript you have the choice of using JSMin or Packer and for CSS you have the choice of using CSSTidy or a simple whitespace and new line removal. This removal code is very simple, but also very safe. The reason I left a few options for both is because sometimes when you start minifying and packing code, things break. It's rare, but possible. Some of these tools have options and those can be passed as well in the configuration.
As an added bonus, this library also will run less files through phpless. Less is a CSS shorthand syntax that will be converted into actual CSS files. The idea is to speed up your development time. After the files are run through phpless and converted, they are then run through CSSTidy and combined into the single CSS file.
These single combined and condensed assets will live in a directory of your choice and be named with a hash string. This hash was generated from all of the assets used. This way every page that has different assets (JavaScript and for the CSS), will have a different combined hash and therefore different file. Updates? If you have an update to a CSS or JavaScript file, you'll have to remove this hashed file so it can be regenerated. In other words, you may not want to enable all this until you're live with your site.
What's this about images? Images can be "optimized" as well. All images placed with the Html image helper on any given template can be output as base64 data URI's if you so choose. The major drawback to using data URI's is that they don't work on IE 6 and IE 7. You can find some JavaScript solution to this problem, ignore this problem, or don't use data URIs. The benefit? Well, if you're caching your view templates, you've now just embedded all images within the HTML code of your view template. So you can probably take a page down to about 3 requests. One for the JS, one for the CSS, and one for the HTML code plus images within. Now you're really starting to save the server quite a bit of work.
So how easy is this to use? How do you use it? Lithium makes this simple. You will run the Libraries::add() method and add li3_assets. Within the same call, you'll pass all of the configuration options. Then in your layout you'll call $this->optimize->styles() and $this->optimize->scripts() instead of $this->styles() and $this->scripts(). So it runs based on the "scripts for layout" feature. Where any script you place within any of your view templates that contain the array option "inline" as false, you will have those be put into the layout template up top within your head section (or wherever you chose in your layout template). The li3_assets library's helper basically intercepts these assets and runs the magic. It then simply returns the HTML code for the assets to be embedded into the page. Simple. So this makes it nice when you want to turn off the optimization. It also makes it flexible so you can have certain layouts that optimize and others that do not. Here's the code all formatted. First, the library configuration.
Libraries::add('li3_assets', array(
'config' => array(
'js' => array(
'compression' => 'packer', // possible values: 'jsmin', 'packer', false (true uses jsmin)
'output_directory' => 'optimized', // directory is from webroot/css if full path is not defined
'packer_encoding' => 'Normal', // level of encoding (only used for packer), possible values: 0,10,62,95 or 'None', 'Numeric', 'Normal', 'High ASCII'
'packer_fast_decode', => true, // default: true
'packer_special_chars' => false // default: false
),
'css' => array(
'compression' => 'tidy', // possible values: true, 'tidy', false
'tidy_template' => 'highest_compression',
'less_debug' => false, // debugs lessphp writing messages to a log file, possible values: true, false
'output_directory' => 'optimized' // directory is from webroot/css if full path is not defined
),
'image' => array(
'compression' => true, // uses base64/data uri, possible values: true, false
'allowed_formats' => array('jpeg', 'jpg', 'jpe', 'png', 'gif') // which images to base64 encode
)
)
));
This shows all of the options, but there are defaults. Then in your layout template put the following within the head section of your template:
echo $this->optimize->scripts(); echo $this->optimize->styles();
That should do it. Now any script in any template using that layout defined like this:
echo $this->html->script('scriptname', array('inline' => false));
...Will be sent to the layout and intercepted and added to the list of scripts to be processed. The same goes for CSS as well.
To convert all images within a template using the Html::image() helper method, you'll simple put at the top of the view template:
$this->optimize->images();
This doesn't output anything, but it does trigger a method that will apply a filter to the Html::image() method. Filters are a real nice feature with Lithium. Now any call to the image() method will be intercepted and the data will be converted to a base64 data URI and returned. I think the use of images as data URI's is limited, but can be a nice feature to have. I think it's especially handy on certain pages where you know a lot of traffic will hit and also helpful for mobile devices. Remember that making another request (connection) takes time and while we don't notice it on high-speed internet, mobile devices will notice it. It also changes when images get loaded and rendered in a browser as well. So I feel it's an under used trick of the trade.
Again, you can grab this library from the repository on the rad-dev site. http://rad-dev.org/li3_assets.




[Back To Blog Index]