The WebApp Wizard Web development made magical

6Dec/114

Assets management with Assetic (and Smarty)

Being quite a web performance geek, I came across various solutions concerning JS and CSS resources management. But this time, I think I found the right one.

At the very beginning, like everyone else, I didn't care much about having 10 javascript and 10 css files included in my web pages. But as my users met performance and strong bandwidth constraints, I started digging into how to improve loading speeds. And then, I fell into web perfs, reading this book. I started applying advice by hand, and as I saw and felt a real improvement, even on my high speed Internet connection, I wanted more. I began making my own automation solutions, and it did quite well the job, even if it was still a bit raw and not so easy to use. But at this time, I used to work alone on my project. As another developer now joins me from time to time, I needed to make minification, compression, caching, and all the rest as painless as possible. My main concern was, at first, to provide an easy way to switch between production and development mode (minified or not), without having to launch any particular command or generating any file. A simple boolean in my configuration had to do the trick. That was an absolute requirement for me.

Then I discovered Assetic thanks to @tijuan_. Assetic is a Symfony2 component, which I tried to use on my non-Symfony project.

And there it is. The thing that I always dreamed about. It allows you to combine and minify the files you want in one single file, and it has several filters you can apply to your assets, like YUI compressor, LESS/SASS parser, Google Closure compiler, among others.

The only problem was: how to integrate this thing neatly? As I use Smarty, some custom block plugin would have been nice. So I made it. The idea is that you tell which files you want to include, which filters you want to apply to them, and whether you're in debug configuration or not. The plugin then takes care of combining and minifying your files if not in debug mode, generating a single file which will be re-generated with a different name if any change is made on the source files. That means you can choose a very aggressive caching strategy without any trouble. The first modification you will make in your source code will result in generating a new file, so the browser will have no other choice than downloading it. You already use some fake parameter in your URLs to avoid caching issues? Not a bad idea, but still not perfect: some proxies will ignore URL query strings. The only 100% reliable option is to generate a totally new file name, which Assetic does.

Just a little example of usage:

{assetic 
    assets="style/reset.css,style/common.css,style/other.css" 
    output="css" 
    build_path="style/build" 
    debug=false 
    filters="yui_css,less" 
    asset_url=asset_url}
    <link rel="stylesheet" href="{$asset_url}">
{/assetic}

Cherry on the cake: it allows you to keep track of dependencies between your files. You don't have to explicitly include the libs you need, assetic-smarty takes care of it, keeping your "files to include" list clean and uncluttered. Don't worry, it won't include the same file twice.

Enough chat, I strongly encourage you to discover Assetic and the associated Smarty plugin.