Thursday, March 10, 2011

Build Time Javascript Code Analysis with JsHint

Javascript can be tough to maintain. The bigger is your project, the harder it will be to ensure that everything is ok. Luckily, there are tools to help you with that.

Paul Irish and Anton Kovalyov recently launched JSHint, a online JavaScript checking tool. The tool is very similar to JSLint, but is designed to be more customizable and community-oriented. JSHint can help you to detect errors and potential problems in JavaScript code and to enforce your team's coding conventions. It is very flexible so you can easily adjust it to your particular coding guidelines and the environment you expect your code to execute in.

The purpose of this post is to show you how to use jsHint as a build-time solution using wro4j maven plugin.

Build Time Javascript Code Analysis

Installing an automatic build process for your projects is very common today and best practice. In the java world Maven is a very popular build tool and has proven its matureness over the years. Using maven to build your client-side project has the following advantages:

  • Find potential problems in your code. Bugs might be identified and breaking code conventions can be detected early.
  • Run the build automatically on a regular base
  • Easily handle refactorings and other small changes
  • Ability to do continuous integration
  • Increase confidence in code quality for each build

Introduce wro4j maven plugin

Since version 1.3.5, wro4j maven plugin provides a new goal called jshint which can help you to start auditing and enforcing JS code through a mechanism like JSHint.
In order to use it you have to follow several simple steps.

Project layout

By default, wro4j maven plugin relies on a typical maven project layout.
This structure can be different, depending on your project. The implicit wro4j maven plugin settings will assume you are using this structure. By default it will search for a file called wro.xml at the following location src/main/webapp/WEB-INF/wro.xml. The location of this file is configurable. You'll find more about all available configuration below. The purpose of wro.xml file is to describe the way static resources are grouped and the order in which these should be processed. By default the plugin will process each resource one by one.

Configure pom.xml

Add wro4j maven plugin to the list of plugins in your web project:

  
    ro.isdc.wro4j
    wro4j-maven-plugin
    ${wro4j.version}
    
      
        compile
        
          jshint
        
      
    
    
      devel,evil,noarg
    
  

${wro4j.version} - is the latest wro4j version (1.3.5). The goal which instructs wro4j to run jshint tool is called jshint. Besides this goal, wro4j maven plugin provides also run goal which performs the compression of the resources (both js & css), but this is not in the scope of this post.
This plugin allows you configure the options used by jshint. Specifying these options is optional. For the complete list of available options, visit the JsHint project homepage. As you can see in the above example, options configuration contains a comma separated values.

Detailed plugin configurations

  • options - comma separated values used to instruct jsHint how to analyze the js code.
  • failNever - boolean flag. When true - the project build will succeed even if there are errors reported by jsHint. By default this value is false.
  • 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.
  • 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/
These parameters gives you enough control to customize the wro4j maven plugin to work with any project structure. When running the plugin and any problems are encountered, you'll see a detailed list of the errors which indicate the file containing the problems, line number where the problem is and the detailed message describing the problem. Here is an example:
[error] 1 errors found while processing resource: classpath:ro/isdc/wro/maven/plugin/js/undef.js Errors are: [ro.isdc.wro.extensions.processor.algorithm.jshint.JsError@19d75ee[
  line=4
  character=4
  reason='jQuery' is not defined.
  evidence=})(jQuery);
]]
These informations should be enough to help you to fix any problems you may have.

Conclusion

Using wro4j maven plugin with jsHint goal can help you to ensure coding standards on your front-end resources when using a mavenized project.

13 comments:

  1. This is a nice article..
    Its very easy to understand ..
    And this article is using to learn something about it..

    c#, dot.net, php tutorial

    Thanks a lot..!

    ReplyDelete
  2. can you please specify how can I generate a result file namely jshint.xml after running above mentioned plugin? to use that in jenkins violations for creating reports?
    Thank you

    ReplyDelete
  3. The violations reports is a feature which is available since version 1.5.0 (latest version is 1.6.1). The path of generated reports is target/wro4j-reports/jshint.xml

    It is possible to change the default path of the file containing reports by adding "reportFile" configuration property.

    ReplyDelete
  4. thank you Alex! much appreciated !
    is there a way to put jshint options in an external file ?
    thx,
    dan

    ReplyDelete
  5. It is not possible to keep jshint options inside an external file out of the box. But you can create a feature request here: http://code.google.com/p/wro4j/issues/list

    ReplyDelete
  6. Hi Alex, Is it possible to customize the rules to be run for jshint?

    ReplyDelete
  7. If by rules you mean "jshint options" than you can add them using 'options' tag (this is described on blog):

    devel,evil,noarg

    ReplyDelete
  8. With the limited functionality offered through the wro4j plugin, is there any benefit to using this instead of jslint4java?

    Also, is there a way to use a different reporter? The one provided is a bit odd to look at after coming from a vanilla JSLint output.

    Thanks!

    ReplyDelete
  9. I did also have one other question/gripe. It looks like this implementation of JSHint only reports problems with 1 file at a time, instead of with all resources. Is there a way to have it continue scanning and reporting past the first file in which it encounters problems?

    ReplyDelete
  10. You can set failNever to true (defaulted to false) option in order to see all errors reported by jshint.

    I don't have much knowledge about features supported by jslint4java. If there are missing features, just let me know. The wro4j maven plugin has several goals, including jshint, csslint & run responsible for implementing various optimization techniques and code analysis using jshint and csslint.

    ReplyDelete
  11. Thanks for the fast response! Using neverFail does let me see all the issues, but it also does not fail the build. My desire is to see all of the errors that JSHint finds, and then fail the build afterward.

    ReplyDelete
  12. The latest release (wro4j-1.6.3) has additional configuration called "failThreshold" which takes a number as argument and is used as a threshold of maximum accepted jshint errors before the build fails. This can be used as alternative approach to see more than one jshint error.

    ReplyDelete
  13. Thanks! I didn't know about that.

    ReplyDelete