More than one year ago, I blogged about pages load time and Jawr. Since then, either my projects were intranet applications where load time was not an issue or we had no say in the tools used. So, I had no possibility to use any of the tools I found then. Now, I’m soon to be faced by an application that will be used by people outside our network and I definitely want the application to be as responsive as possible. Armed with my previous Yahoo best practices, I hunted on the web for tools that could help me enforce them.
One rule I hold in high esteem is: minimize the number of HTTP requests. I think this rule has the most impact since browsers only send at most 2 HTTP requests at a time. Let’s take a classical example. Buttons play a big part in many applications and most of the time, you put an icon on them in order to tie them to the action in the user’s mind. This is simply done like so:
<button><img src="path/to/my/image" />Label</button>
This means that any screen that display more than one button type has the potential to be slow.
One way to dramatically decrease the number of requests is to aggregate all the images in one and use CSS background images.
The latter is available since the first version of CSS, just specify the background-image
attribute to display the image behind an element .
This usage is called CSS Sprites.
The code now looks like:
<button class="update">Label</button>
button.update {
background-image: url('path/to/my/image');
background-repeat: no-repeat;
}
The astute reader will have remarked that the previous code has the same effect as the <img>
in the <button>
.
The real usage is to use only the portion of the master image that we want, somehting akin to that:
button.update {
background: transparent url('path/to/my/aggregate') -50px -50px no-repeat;
}
To aggregate the master image requires the right image tool. To compute the portion we want for each button is a pain in the butt (to speak politely).
Luckily, my old friend Jawr has the right feature to help me. Since version 3.2, it includes SmartSprites, a product that just does all aggregating and computing for me. How does that work? Just by putting some comments in your CSS:
- to declare how the master(s) image(s) will be constructed
- to tell which sprite will take part in which master image
/** sprite: master-sprite-gif; sprite-image: url('../img/master-sprite.gif'); sprite-layout: vertical */
button.one {
background-image: url('../img/certificate_preferences.gif'); /** sprite-ref: master-sprite-gif; */
}
button.two {
background-image: url('../img/inbox_into.gif'); /** sprite-ref: master-sprite-gif; */
}
button.three {
background-image: url('../img/mail_forward.gif'); /** sprite-ref: master-sprite-gif; */
}
The previous CSS is an example by which all three GIFs will be found at runtime under ../img/master-sprite.gif
.
If you look at the generated CSS, it will have the following look:
button.one{background-image:url('../cb3648025844/img/master-sprite.gif');background-position:left -0px;}
button.two{background-image:url('../cb3648025844/img/master-sprite.gif');background-position:left -48px;}
button.three{background-image:url('../cb3648025844/img/master-sprite.gif');background-position:left -96px;}
Of course, the real generated CSS will have been concatenated and minified (see below).
Note: I’m not a GIF expert but I suspect original GIFs should have similar color tables, otherwise, the aggregated GIF will look really strange.
However, Jawr also provides some very interesting features, both old and new:
- minification, for both CSS and JavaScript. You can also choose the minifying engine (embedded, JSMin or YUI Compressor). The latter is even able to obfuscate your source, thus even making your JS even lighter in the process
- license inclusion, so that even minified sources can display their license
- runtime GZip compression if the client browser supports it
- HTTP header management so that requests for the same resources (beside the first) will be answered by a HTTP 304 - Not Modified code, thus avoiding unnecessary network traffic
- i18n management in order to use Java standard properties files for internationalized messages in your JavaScript
- JavaScript to use Jawr without taglibs in plain HTML pages (though it is not recommended since it adds a script to the page, thus another HTTP request)
- possibility of extension, with new pre- and post- processors
- ability to switch between development mode (no modification for resources) and production (virtual resources served by Jawr)
- bundle preprocessing, so that the processing is not done at startup but instead at build time: this can be done either by calling an Ant task or by configuring a Maven plugin
- for truly engaged application server administrators, support for JMX
During the last year, it seems Jawr has gained some nice upgrades. I don’t know how many people truly use it but I think it deserves some interest when you need to optimize performance on the page loading time front.
You can download the sources for this article in Eclipse/Maven format here.