Front-end and assets management with Assetic in Symfony2

One of the most important things in Internet these days is page loading speed. You can have the fastest MySQL installation, many distributed Memcached servers, etc. but if your static content is not properly handled you will get a low page speed degree.

Some people might think that this is just a Google (or YSlow) metric which is nice to have but it is not a big deal. And the truth is that there are many studies that prove that having a slow loading page time becomes poor conversion in e-commerce. And even if your site is not an e-commerce, if your users experience delays while browsing it, they will just go somewhere else.

So, one of the most important things in modern websites is front-end engineering. Unfortunately, in Spain, most managers treat them as simple “layout guys” or even “those freaks” but in my opinion they are one of the most important parts of the web development team. So, big respect to all you guys that are still dealing with Explorer 7 (or even infamous IE6) but try to introduce HTML5 and CSS3 features without telling your managers.

Getting back to Symfony2, this great framework would be incomplete without tools to help us deal with this stuff. And Assetic was the library chosen to do so. It is true that for better performance we should combine good assetic practices with some caching (maybe combining Symfony2 HTTP caching with Varnish or even some CDN like Akamai) but this will be covered in a future post.

CSS and JS storage in Symfony2

A bundle in Symfony is just “a group of files that go together”. And CSS, JS, icons and small images are no exception. They will be stored in [Bundle_Folder]/Resources/public. And one good thing to do is to split them in the typical css, js and img (or whatever you like) folders.

One might think “hey! this folder is not public in Apache2”, and they are right, but here comes assetic configuration to the rescue.

Assetic basic configuration

When we are in development environment, we will just work in those files (there is nothing in the public folder).
And it works thanks to the following configurations:

– in config_dev.yml you may have noticed

assetic:
    use_controller: true

– And in config.yml we might have something like this

assetic:
    debug:          %kernel.debug%
    use_controller: false
    filters:
        cssrewrite: ~
        yui_css:
            jar: "/var/www/yuicompressor-2.4.2.jar"
        yui_js:
            jar: "/var/www/yuicompressor-2.4.2.jar"

And this means that while we are in development environment, Assetic looks for the files inside our Bundle and automatically processes them on each request (even when the filters we might have defined, like LESS compiling for instance)

But when we deploy Symfony2 in PRE or PROD environments, assetic:dump and assets:install command automatically process all those files and generates a single one, executing all those filters to generate the best possible CSS / JS content.

Some tweaks

Probably most of you have heard about YUI Compressor. There are other libraries, like Google Closure, but the purpose is the same: minimize your CSS and JS files as much as possible without losing functionality. And how is this achieved?

– Eliminate whitespacing in CSS and JS: it is true that sending gzip files will eliminate most of the overhead, but why send stupid data through the web?
– Minimize HTTP requests combining all CSS and JS in one file
– Even reduce JS length renaming variables with short names like a,b,c and so on.

This process can take some time and it is annoying if everything gets executed at every request while we are developing… so we can do something like this in Twig

 {% block stylesheets %}
  {% stylesheets '@OurBundle/Resources/public/css/*.css' filter='?yui_css' output='css/minified.css' %}
    <link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
  {% endstylesheets %}
 {% endblock %}

And with the ?yui_css filter we are telling assetic to only execute yui_css filtering when debug mode is off, so in our development environment it won’t get executed.

Another thing that is getting more and more popular is the use of LESS for CSS development.

According to Less, Assetic can use node.js less compiler so we should have installed both node.js, node package manager and less package. (There is also LessPHP support, but at the time of writing, LessPHP still lacks some features and I have not tested this configuration.)

To install node.js and less

– At the time of writing I have only been able to get less compiler to work on node.js 0.4.x, in 0.5 there seems to be a problem with some global variables (I am not a node.js expert so maybe someone can give more feedback)
– Instructions on getting installed node.js and npm are different for every SO but in Ubuntu you can follow this. Anyway, there are many links to that and the only thing that really matters is to install node 0.4 for the moment.
– And finally you can install less compiler with “sudo npm install less” (basically npm is to node.js what gem is to ruby)

And of course, LESS via node.js can be configured in our yml file as follows:

assetic:
  less:
    node: /usr/local/bin/node
    node_paths: [/usr/local/lib/node]

(node and node_paths are only necessary if you want to override default configurations depending on your installation)

And we would do something like this in Twig:

{% block stylesheets %}
  {% stylesheets '@OurBundle/Resources/public/less/*.less' filter='less,?yui_css' output='css/minified.css' %}
    <link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
  {% endstylesheets %}
 {% endblock %}

There are many other filters in Assetic (like CSSEmbed, SASS, CoffeeScript, OptiPNG, JPEG Optimizer…) so there are no excuses to not optimize our front-end!

Hope you have liked this introduction to Assetic and let’s hope it won’t take so long for a new post!

You may also like...

2 Responses

  1. JumpingJack says:

    I like the post. Makes things quite clear. Looking forward to more on frontend-development with Symfony2,

  2. Ricard Clau says:

    Thanks for your comment!

    Right now we are starting to use LESS and we will also configure CSSEmbed all under Assetic so, for sure, there will be at least a new post on this stuff in some weeks time