lunes, junio 06, 2011

I Hitched A Ride With Chris McCandless, I Stepped In The Wild With Chris McCandless, And I Felt Alive With Chris McCandless. I Was Wide Awake In The Dream. (The Ballad of Chris McCandless - Ellis Paul)


Now-days, jQuery are becoming so popular in client-side of web development. jQuery is a cross-browser JavaScript library designed to simplify the client-side scripting of HTML. jQuery itself is composed by "one" file called jquery-x.x.x.min.js. With only one Javascript there is no performance problem. But with jQuery has been appeared some "addons/plugins" that uses this library. An example could be jQueryUI http://jqueryui.com/ but more can be found at http://plugins.jquery.com/. Each of these addons contain their own Javascript file. For example jQueryUI contains apart from jQuery file, jquery-ui-x.x.x.custom.min.js and one CSS file, so in this case in a web page two Javascript and a CSS elements are defined. As more and more extensions are used, more Javascript files are required. And more scripts imply more connections to server, so for example if three Scripts and one CSS are defined, four connections from browser to server are required.

Because of these amounts of connections, downloading time is increased; content negotiation and the fact that normally there will be only two concurrent connections to the same host, produces an overhead that results in a long page loading time. For example, it is faster to serve a 8KB script file than  eight of 1KB.



For speeding up your application, would be desirable that only one Javascript and one CSS were downloaded. Arrived at this point, one can think next approach; using a Maven plugin or any other automatic system, that opens all js files and concatenate all of them in a single file. This approach is valid, but has a major problem, any small change forces developer to re-run build script before changes can be tested. Also you are duplicating same information in two or more files, so you must take care assuring consistency between them. 

The goal for Jawr is to provide a system to easily map resources to bundles using a simple descriptor, and a tag library to import these bundles to JSP pages.


In summary, using Jawr taglib you define a fictional Javascript file (for example widgets.js) in JSP; this file does not exist physically anywhere. Then in Jawr configuration file (jawr.properties), you map which Javascript files should be appended when client browser requests "unreal" Javascript file (widgets.js). So from developers' point of view you could have a hierarchy of several js files, while from client-side (browser), only one file is sent.

Using Jawr in only Servlet based web applications are easy. Jawr comes with a Servlet net.jawr.web.servlet.JawrServlet, where you define Jawr configuration file, and a workable mapping for js extensions. (http://jawr.java.net/docs/servlet.html).

But in case of Spring MVC web applications, things are bit complicated. Jawr provides a Spring controller, that acts the same manner as previous Servlet, but instead of using servlet-mapping tag you must create a SimpleUrlHandlerMapping.

In this post I will explain you how to create a Spring MVC jQuery web application integrated with Jawr. Let's start with a Spring MVC application that does not contain any references to Jawr.

JSP page contains definitions for all elements required by jQuery plus one custom script file (defining a() function).

and in servlet-context.xml static resources (Scripts and CSS) mapped correctly.


This web application contains four references to static resources, so load diagram looks like:



As you can see there is no file aggregation. With Jawr these four connections can be reduced to two, one for all Javascript files and another one for CSS.

Let's start mapping resources. This is specified in jawr.properties file that should be present in root classpath:

First line enables the ability to serve gzipped resources to browsers that support it. Next two lines are required for mapping script files. jawr.js.bundle.[bundleName].id is the property where you specify the name of fictional Javascript file. This name will be the one used in JSP. The other line jawr.js.bundle.[bundleName].mappings is where you indicate all Javascript files that should be appended when jawr.js.bundle.[bundleName].id file is requested by browser. In previous example when your JSP page is requesting /script/all.js resource, Jawr will join a.js, jquery-1.5.1.min.js and jquery-ui-1.8.13.custom.min.js and sent back the result to client-browser. Last lines are the same but for CSS files.

Next step is changing JSP, so instead of having one reference for each file, only contains one reference to jawr.js.bundle.all.id value.


Jawr provides a tag library used to generate tags that import bundles to clients and these tags are <jawr:script/> and <jawr:style/>.

Unlike Servlet approach, web.xml don't have to be modified, Jawr provides a Spring controller that must be configured as you would do in Servlet approach.

Next step is configuring Spring Controller. Jawr site provides documentation about how to configure a Spring MVC with Jawr. The example provided uses old-school fashion configuration controllers using SimpleUrlHandlerMapping. But because I always use annotated controllers and I don't want to have some controllers defined with annotations and other ones in UrlMapping, in this post Jawr Spring Controller has been extended for being used with annotations.

For implementing Jawr Spring Controller with annotations I have only created an aggregation between annotated controller and Jawr controller. So class looks:


and the same approach for CSS is used but changing RequestMapping to /**/*.css and Qualifier to jawrCSSController.

As you probably noticed, two Jawr controllers are used, one for Javascript and another for CSS. This is because Jawr requires that you specify if code to optimize is Script or StyleSheet. Spring configuration looks:

Finally <resources> tag from servlet-context.xml should be changed to:

<resources mapping="/css/images/**" location="/css/images/" />

because now only images are required to be served as static resources.

With previous changes applied, load diagram looks like:



See that only one connection for all Javascript files are performed. And also see how downloaded time has been improved from first version. Times showed here are not calculated in a scientific way, they are calculated from localhost, but if you compare previous diagram with this diagram, you can see an improvement.

You can also speed up even more your response time using a cache strategy, but this topic is out of scope of this document.

I wish you have found this post useful, and now before using jQuery scripts, prepare your environment with Jawr so your application can be loaded even faster.

I hope you find this post useful.

Download Code.

Music: http://www.youtube.com/watch?v=3tdQx4Y3I2c

3 comentarios:

Anónimo dijo...

Interesting... Maybe we´ll test JAWR in our project.

http://code.google.com/p/uda/

Anónimo dijo...

Hi Alex,
I have tried to use your example but I am having a problem with the Tag Library. I receive this problem Unable to locate tag library for uri http://jawr.net/tags

The URI "http://jawr.net/tags" is not found. Any ideas?

thanks
Ray

Alex dijo...

I have updated post with Eclipse project of the example used in this entry.