Developing Javascript Web Apps with Maven: Initial Research

Monday, May 13, 2013

In this post I'm going to write down my initial research on creating a Maven based toolset to develop Javascript intensive web applications. The guys at Codehaus already have a project with the same goal, and I've borrowed some ideas from them. His approach doesn't fit well with my needs, but you should take a look a it, maybe it works for you.

I've just started to scratch the surface and I don't address things like Javascript minifying, AMD and the like. These are the problems I've been working on

  • Using a separate directory to store Javascript source and test files.
  • Packaging Javascript libraries as Maven dependencies and using the Maven dependency mechanism to retrieve transitive dependencies.
  • Including Javascript unit tests in the Maven builds
  • Enabling rapid develop/test cycles

Javascript Sources as First Level Citizens

If you are developing a Javascript intensive web app it makes no sense to hide Javascript sources under the webapp directory. So I use a js directory under both, src/main and src/test

directories. Then a I configure the mave-war-plugin to put those files in the proper place at package time:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-war-plugin</artifactId>
  <version>2.3</version>
  <configuration>
    <webResources>
      <resource>
        <directory>src/main/js</directory>
        <targetPath>js</targetPath>
      </resource>
    </webResources>
  </configuration>
</plugin>

Javascript Libraries as Maven Dependencies

Coming from a Java/Maven background, when you start developing Javascript intensive apps thing you miss more is a centralized artifact repository for Javascript libraries. Codehaus is doing a timid attempt to use the central Maven repository to host Javascript dependencies. Codehaus's approach has a major flaw (IMHO), it deals only with Javascript sources, forgetting about other types of files usually bounded to a given dependency. For example, a jQuery UI dependency should include all, the Javascript source and the associated CSS and image files.

My solution (borrowed from this blog post relies on a feature introduced by the Servlet 3.0 API. Basically any file in the META-INF/resources directory within any JAR in the WEB-INF/lib is served a a static resource by the webapp. As an example, this is my Maven project to generate a JAR packaged chosen-jquery

-src
    |-main
    | |-resources
    | | |-META-INF
    | | | |-resources
    | | | | |-css
    | | | | | |-lib
    | | | | | | |-chosen.css
    | | | | | | |-chosen-sprite.png
    | | | | | | |-chosen-sprite@2.png
    | | | | |-js
    | | | | | |-lib
    | | | | | | |-chosen.js
 - pom.xml

And this those are the contents for the pom.xml, including a dependency on jQuery

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <groupId>es.cgalesanco.javascript-libraries</groupId>
    <artifactId>javascript-libraries</artifactId>
    1.0-SNAPSHOT
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>chosen-jquery</artifactId>
  <version>0.9.13</version>

  <dependencies>
    <dependency>
      <groupId>es.cgalesanco.javascript-libraries</groupId>
      <artifactId>jquery</artifactId>
      <version>1.9.1</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>

When generating these dependencies I'm following a couple of conventions. The main Javascript file is stored in under js/lib without any version designation; this allows changing the version to be used just by changing the Maven dependency, without any change to source files. The same is true for any other file potentially referenceable from source files.

Javascript Unit Tests: Jasmine Maven Plugin

If you are doing Javascript intensive development you should be doing intensive Javascript unit testing, shouldn't you?. I've found Jasmine pretty handy for Javascript unit testing, and the Jasmine Maven plugin integrates this test framework into Maven. I initially had some issues executing the test goal as it used HtmlUnit for running test during the test phase, but from version 1.3.1.2 onwards you can use GhostDriver, a Selenium WebDriver for PhantomJS, to execute tests against a WebKit browser

The Jasmine maven plugin doesn't resolve properly the dependencies inside the META-INF/resources, so I've created a pull request to solve this issue. Meanwhile you can get my modified plugin from here. This is my configuration for the Jasmine plugin (PhantomJS 1.9 must be in your path for the test goal to work):

<plugin>
  <groupId>com.github.searls</groupId>
  <artifactId>jasmine-maven-plugin</artifactId>
  <version>1.3.1.3-SNAPSHOT</version>
  <configuration>
    <jsSrcDir>src/main/js</jsSrcDir>
    <jsTestSrcDir>src/test/js</jsTestSrcDir>
    <webDriverClassName>org.openqa.selenium.phantomjs.PhantomJSDriver</webDriverClassName>
  </configuration>
</plugin>

And this is a minimal Jasmine spec (unit test) taken from the Jasmine web site

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});

Jetty for Rapid Develop-Test Cycles

Storing your Javascript files in src/main/js has a major drawback for daily development, it doesn't play well with the Jetty Maven plugin. You can use jetty:run-exploded instead of jetty:run, so that the Javascript sources get copied to its final destination within the webapp, but this has two problems:

  1. Generating the exploded web app can be time consuming for any mid-sized application
  2. Changes on the original Javascript sources are not immediatly reflected by the Jetty server (who is serving the copies inside the exploded webapp)

Again, I've submitted a patch to the Jetty project for the Jetty Maven plugin to honor the webResources configuration in the Maven WAR plugin. Meanwhile you can find my modified Jetty plugin from my Github repository

7 comments :

  1. Web Application Development
    This is really interesting, You’re a very skilled blogger. I have joined your feed and stay up for in the hunt for extra of your fantastic post. Also, I have shared your website in my social networks.

    ReplyDelete
  2. This is a very amazing post for cheap web hosting services. in this post, you have provided all the basic information regarding.

    website builder for reseller

    ReplyDelete
  3. Comfortabl y, the post is really the freshest on that deserving topic. I harmonise with your conclusions and definitely will thirstily look forward to your next updates.

    private label website builder

    ReplyDelete
  4. Thank you for the link building list.I am going jot down this because it will help me a lot.Great blog! Please keep on posting such blog.

    white label website builder

    ReplyDelete
  5. It is extremely relaxing to find honest, iphone recambios dependable along with productive support currently but North playground Apple computer Maintenance is precisely that. His 5 legend comments are location on. Mac pc Reserve water damage and mold fix fulfilled me at his workplace time we requested to look into my destroyed iPhone 6 exhibits as well as altered it, analyzed it along with this inside my concerned palm within absolutely no time….

    ReplyDelete
  6. The article was up to the point and described the information very effectively. Thanks to blog author for wonderful and informative post.
    website development

    ReplyDelete
  7. Best Indian WordPress Developers who are not only skilled in their technology but also keeps their promise to create a robust code for your solutions and save your money! The current scenarios of technology have raised the status of web development in India.

    ReplyDelete