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.

4 comments:

  1. Great info here... thanks for the writeup. One note though is that the xml examples given above have all lower-case tags. I had to fix them to camelCase to make them work.

    ReplyDelete
  2. Thanks for reporting this. The problem is with syntax highlighter which transforms everything to lowercase... I'll check if the newer version fix this problem.

    ReplyDelete
  3. Thanks for the excellent plugin. How do I specify arguments for Google Closure compiler plugin and generate source map?

    ReplyDelete
  4. @Manikanta - this is not possible yet. But there is an open issue. If you need this feature soon and have some spare time to contribute, you're welcome :).

    ReplyDelete