Sunday, February 13, 2011

Simple client-side build system with wro4j command line tool

Intro

Wro4j is a free and Open Source Java project which will help you to improve your web application page loading time. It can help you to keep your static resources (js & css) well organized, merge & minify them at run-time (using a simple filter) or build-time (using maven plugin or a command line tool) and has a dozen of other features you may find useful when dealing with web resources.

The main target of wro4j framework is help to speed up web applications to be optimized by implementing a couple of recommended performance rules.

Starting with wro4j-1.3.4 release, it is not limited anymore to java development environment. If, for instance, you are developing a js framework with many small modules (ex: jquery, yui, mootools, etc) or if you are working on the client-side of a large web project, then wro4j can help you to easily organize all your static resources (css/js) and build them (merge and minimize) using a simple command line tool. The only prerequisite is to install jdk-1.6 on your machine.

This post will focus on description of the wro4j command line tool.

Target audience: this post may be interesting not only for java developers, but also for web developers (using any kind of technology) and css/javascript framework creators.

Getting Started

Let's make it practical. We'll show how wro4j can help building the jquery tools project.

Currently, it uses ant build script (build.xml) to describe how the js resources are merged and minimized. Also it supports google closure compiler only. Switching to another compressor is not supported. Using an ant script can be a good solution for many similar projects, but it also can be quite complex. Having a verbose and complex script is very hard to understand and maintain. Isn't there a simpler solution?

Installation Steps

With new wro4j command line tool, you can achieve the same results with minimum effort. All you have to do, is to follow the following steps:

  1. Add wro4j-runner-1.3.4-jar-with-dependencies.jar. In our case, we add it to the lib folder (just where other jar files resides). The default relative context path depends on the location of the jar (this can be changed with an argument we'll get back to this later).
  2. Create wro.xml file and add it in the same folder where the jar is located. . This file describes how you want your resources to be merged and the resources location. For more details about wro.xml, visit this page. Here is an example:
    
      
        /jquery-1.4.2.js
        /../src/**.js 
      
    
    
  3. Run the following in your console:
    java -jar wro4j-runner-1.3.4-jar-with-dependencies.jar
    
    As a result, a new folder (called 'wro') will be created. It will have one file: all.js containing a merged content of all js files from ui folder (as described in wro.xml).

Minimization (compression) configuration

Of course, it would be nice to have the all.js file compressed. In order to do that, make a small change to the console script:
java -jar wro4j-runner-1.3.4-jar-with-dependencies.jar -m
Adding -m attribute, inform the wro4j runner to minimize the scripts. By default, it uses JSMin processor for js compression. You can easily switch this compressor with other, here is an example:
java -jar wro4j-runner-1.3.4-jar-with-dependencies.jar -m -c uglifyJs
This will inform wro4j runner to use UglifyJs compressor instead. Similarly, you can use other compressor.

You don't have to worry when invoking the wro4j-runner with wrong arguments, it will inform you about the cause of the problem and in some cases can suggest possible solutions. Also, when everything is ok, you will see in command line the details about processing and total duration of the operation.

Supported Compressors

Currently wro4j-runner support the following js compressors:
  • jsMin - For JsMin compressor. This one is used by default if you don't specify any.
  • uglifyJs - For UglifyJs compressor
  • beautifyJs - Exactly the opposite of the uglifyJs, it does what it says - makes compressed code readable.
  • googleClosureSimple - For Google Closure Compiler with simple optimization
  • googleClosureAdvanced - For Google Closure Compiler with advanced optimization
  • yuiJsMin - For YUI compressor with no munge
  • yuiJsMinAdvanced - For YUI compressor with munge
  • packerJs - Uses Dean Edwards Packer compressor (version 3.1)
  • dojoShrinksafe - Uses Dojo Shrinksafe compressor.

You can easily switch between any of the preferred compressors, depending on your tastes or preferences. Maybe for some projects one compressor suites better than other. The nice part is that wro4j can support any possible existing javascript compressors. For more details visit wro4j project home page.

Wro4j runner arguments

Here you'll find all the arguments supported by wro4j runner tool.
  • -m or --minimize - Turns on the minimization by applying the default or specified compressor
  • -c or --compressor - Name of the compressor to use. The complete list of supported compressors was described earlier.
  • -i or --ignoreMissingResources - This is useful when you want the runner to do its job even when you specify an invalid resource in your wro.xml. By default missing resources are not ignored.
  • --targetGroups ${GROUPS} - Comma separated list of groups (defined in wro.xml) to process. If you don't specify this argument, all existing groups will be processed and for each of them will be created a file.
  • --destinationFolder ${PATH} - The folder where the target groups will be generated. By default it will create a folder called wro
  • --wroFile ${PATH} - location of the wro.xml file. By default runner will search it in the current folder.
  • --contextFolder ${PATH} - folder used as a root of the context relative resources (or where to search when you have a resource starting with / character). By default this is the current folder.

You can find the updated version of jquery tools project using the new wro4j runner for merging and compressing resources at the following location: https://github.com/alexo/jquerytools.

Summary

Starting with wro4j-1.3.4 release, you can easily maintain, merge and minimize client-side resources (css & js) with wro4j-runner command line tool. By following 3 simple steps, you can compress your static resources into a single compressed file, using one of 8 supported javascript compressor. This tool is easily customizable, flexible and can help you simplify the way you are building your client-side project.

Resources

  1. Wro4j project home
  2. Wro4j github homepage
  3. Jquery tools project page - used as an example for this post
  4. Jquery tools using wro4j runner example

Sunday, January 30, 2011

Using Google Closure Compiler with wro4j maven plugin

This post is about how you can integrate Google Closure Compiler into your project with wro4j maven plugin. Google Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs.

Since 9 december 2010 Google Closure Compiler is on Maven Central Repo. Nevertheless, there are people who complains that there is no official maven plugin which to help you easily to integrate it into their project. Bellow is a comment: (you can find it here)

Let me get this straight: it took over a year for someone at Google to figure out how to get the library into Maven, and still nobody realized at that point there needed to be a plugin and some documentation on how to use the plugin? And now no one at Google can figure out how to write a Maven plugin, so this issue has been "fixed" by saying that there is some third-party plugin---that according to the documentation requires you to manually install the Google Closure Compiler? I'm sure there are many like me who just want to plug the Google Closure Compiler into their Maven project; have found this page; realized the state of understanding of Maven here (as stated in the comments); and moved on to find an alternative.
Wro4j does provide google closure support since 1.3.0 version is out. Maybe because the wiki documentation is not enough, I'll describe how to do it in this post. The wro4j maven plugin, is a very handy tool when you need a build time solution for merging and minimizing resources used in the project. There is also a runtime solution which is as easy as adding a simple filter in web.xml, but here we will focus only on how to use it as a build time solution.

Configuration


Project Structure

A typical 'mavenized' web project has the following structure:
This structure can be different, depending on your project. The implicit wro4j maven plugin settings will assume you are using this structure. What is important for wro4j maven plugin is the following: the location of wro.xml file (the group of resources descriptor) and the location of context folder (used to compute context relative path of resources). Both of these values are configurable.

Create wro.xml

First step is to create wro.xml file which defines the way you want your resources to be grouped (how to merge them). You can find more details about wro.xml file format here. This is a sample wro.xml:


  
    /static/css/lib/global-whitespace-reset.css
    /static/css/lib/tools.css
    /static/css/lib/base.css
    /static/css/lib/layout.css

    /static/js/modernizr/modernizr-1.1.min.js
    /static/js/lib/core.js
    /static/js/lib/site.js
  

Add wro4j maven plugin dependency to pom.xml

Add the following plugin dependency to your web project:

  
    ro.isdc.wro4j
    wro4j-maven-plugin
    ${wro4j.version}
  

${wro4j.version} is a placeholder for wro4j version (latest is 1.3.3). This is the minimum necessary to get started. At this point, you can already start using it by running the following in command line:
mvn wro4j:run
As a result, you'll see that for each defined group in wro.xml, you'll find a minimized version of the resources at the following default location: /src/main/webapp/wro/. At this point, you are not yet using google closure compiler for compressing javascript resources. Instead, a default minimizer is used. In order to replace it with google closure compiler, you have to apply some more advanced configurations on wro4j maven plugin.

Advanced plugin configurations

Below is an example of how you can configure wro4j maven plugin with all possible parameters:

  
    ro.isdc.wro4j
    wro4j-maven-plugin
    ${wro4j.version}
    
      
        compile
        
          run
        
      
    
    
      all
      true
      ${basedir}/src/main/webapp/wro/
      d:/static/css/
      d:/static/js/
      ${basedir}/src/main/webapp/
      ${basedir}/src/main/webapp/WEB-INF/wro.xml
      ro.isdc.wro.extensions.manager.standalone.GoogleStandaloneManagerFactory
      false
    
  

Notice the following:
ro.isdc.wro.extensions.manager.standalone.GoogleStandaloneManagerFactory
This instructs wro4j maven plugin to use google closure compiler. And here is a complete list with explanation of all supported parameters (all of them are optional, if you don't want to specify them, the default value will be used instead).
  • minimize - a flag used to turn minimization on or off. This parameter is optional and by default its value is true.
  • targetGroups - (optional) a comma separated list of groups you want to build. If you do not specify this parameter, a file for each defined group will be generated.
  • wroManagerFactory - Optional attribute, used to specify a custom implementation of MavenContextAwareManagerFactory interface. When this tag is not specified, a default implementation is used. This attribute is useful if you want to configure other processors than default one.
  • wroFile - the location of wro.xml file which defines how resources are grouped. By default its value is this: ${basedir}/src/main/webapp/WEB-INF/wro.xml . If you have a different project structure or a different location of wro.xml, then you should change the value of this parameter.
  • contextFolder - defines the location of web application context, useful for locating resources relative to servletContext. By default its value is: ${basedir}/src/main/webapp/
  • destinationFolder - folder where the result merged resources will be created.
  • cssDestinationFolder - folder where the css merged resources will be created
  • jsDestinationFolder - folder where the js merged resources will be created
  • ignoreMissingResources - if false, the build will fail if at least one resource is missing or cannot be accessed, otherwise only a warning will be displayed.
These parameters gives you enough control to customize the wro4j maven plugin to work with any project structure.

Conclusions

Though there are no official maven plugin for google closure compiler, you can use it with wro4j maven plugin. All you have to do, is to create wro.xml file (for describing how resources are grouped), add wro4j maven plugin to pom.xml and enjoy the outcome.

Sunday, September 5, 2010

Syntax Highlighting in Your Blog

This article describes about how syntaxHighlighter javascript can help you to add code snippets to your blog and how wro4j can help you with it.

There are plenty of sites which helps you to start bloging. But when your blog posts contains some code, suddenly you are not sure anymore which suites you better. Some of them accepts markdown markup language, which allows you to insert code easily without bothering about formatting. Unfortunately markdown has its own disadvantages. For instance,  its hard to define code boundaries or if you want to add xml code, you have to manually escape it. That can be annoying and time consuming.

While searching for an alternative, I have found a javascript widget which solves my problem. It is called SyntaxHighlighter was developed by Alex Gorbatchev and it fits perfectly for my needs. It is very easy to install and it doesn't have the problems I had with markdown.

Below is the example of how the markdown syntax looks like: And this is the example of syntaxHighlighter usage:
For more examples, visit documentation about syntax highlighter installation.
Syntax Highlighter is a great javascript widget, but in order to support formatting for different languages, you have to include a lot of js & css resources. For each language, syntaxHighighter with a dedicated javascript file of the following format: shBrush<language>.js (ex: shBrushJava.js). That means that if you want to support formatting for 10 different programming languages, you have to include more than 10 resources (besides those). This can damage your blog page loading performance. And this is why I decided to use wro4j to fix this problem.

Wro4j maven plugin seemed to be a natural choice to solve this use-case. I have downloaded the syntaxHighlighter distribution and added it to wro4j-examples project which has the maven infrastracture ready. You can checkout the wro4j code from github and play yourself with it.

The first step was to create the configuration file which describes how to group the resources into the bundles:


The next step is to configure pom.xml of the project and instruct it to use wro4j maven plugin

Replace the ${wro4j.version} placeholder with actual wro4j version.
This is the simplest way to make it work. The wro4j maven plugin is very easy to configure, so that instead of default js & css compressor we could use others, like YUI or Google closure compressors. This can be done this way:

If you want to use google closure compressor, use the following value for wroManagerFactory configuration: ro.isdc.wro.extensions.manager.standalone.GoogleStandaloneManagerFactory
In order to run it, we have two options:
1) As a part of the build process of the project. (run mvn install command)
2) Explicitly run wro4j maven plugin: mvn wro4j:run

As a result, you should see the groups bundled under the target/wro folder (the destination folder is also configurable)

To make the resources public available, these resources were copied to google code repository, under the following path:
1) http://wro4j.googlecode.com/svn/wiki/static/syntaxHighlighter/3.0.83/syntaxHighlighter.js
2) http://wro4j.googlecode.com/svn/wiki/static/syntaxHighlighter/3.0.83/syntaxHighlighter.css

One small note regarding the committing these resources to google code repository: by defualt the files commited with svn client have text/plain mime type. This could cause a problem if you expect a different mime type. If you need a different mime type, you have to specify it with your preferred svn client by adding svn:mime-type property with expected value (ex: text/css). Thus, when you will include this resource into your page, it will be served with correct content type in response header.

The installation of the syntaxHighlighter javascript widget is trivial. Just add the resource to the head of the blog template:

    <script src='http://wro4j.googlecode.com/svn/wiki/static/syntaxHighlighter/3.0.83/syntaxHighlighter.js' type='text/javascript' />
    <link href='http://wro4j.googlecode.com/svn/wiki/static/syntaxHighlighter/3.0.83/syntaxHighlighter.css' rel='stylesheet' type='text/css' />