Last week, I released version 1.0 of my JS Plugin for Gradle. It’s come a long way since its inception, and I wanted to explain what it does and where it’s headed in the future.

Features of the JS plugin

I’d argue the most common (and important) task a build can do with regard to JavaScript is reduce HTTP requests to improve site speed, so that’s the first thing I tackled with the plugin.

combineJs {
    source = javascript.source.libs.js.files + javascript.source.custom.js.files
    dest = file("${buildDir}/all.js")

// Uses Google Closure Compiler
minifyJs {
    // Tell the task to consume the output of combineJs
    source = combineJs
    dest = file("${buildDir}/all-min.js")

def version = "whatever"
gzipJs {
    source = minifyJs
    dest = file("${buildDir}/all-${version}.min.js")

You might also want to make sure your code is linted to prevent possible bugs, so I’ve included JSHint support:

jshint {
    source = javascript.source.custom.js.files
    dest = file("${buildDir}/jshint.out")

There are a bunch of JS documentation tools out there, and I have started by adding support for JSDoc 3

jsdoc {
    source = javascript.source.custom.js.files
    destinationDir = buildDir

Finally, Nicolas Zakas developed a tool that converts Java properties to JSON or JSON-P called Props2Js:

props2Js {
    source = file("${projectDir}/src/test/resources/")
    dest = file("${buildDir}/props.jsonp")
    props {
        type = 'jsonp'
        functionName = 'callbackFn'

I have a bunch of examples of things you can do without a plugin, like run QUnit tests with PhantomJS or upload JS files to a CDN as part of my stacktrace.js build and build.

You can also see detailed tasks usage and options on the Gradle JS project site.

Screencast Intro

I have recorded a screencast where I combine, minify and version/gzip JavaScript for a small site, then update all references to the new JS file version and upload to Amazon S3. Those in RSS readers can check this screencast on Youtube.

This is the very same process as what I do for this site.

Pros and cons of this tool

Most of the good and the bad come from having tighter JVM integration than tools like Grunt. Gradle can:

  • More easily take advantage of tools written in Java, JRuby, Groovy, Scala or other JVM languages.
  • There are a bunch of ant tasks already written that Gradle can use out-of-the-box
  • Better outputs (like JUnit XML for tests) for Continuous Integration

The limitations and downsides I see are:

  • NodeJS integration. There is no reason you can’t run node from Gradle, but integration won’t be better than strings in and strings out until we have decent Node-JVM integration.
  • While Gradle can use ant tasks, Grunt and Maven have a larger set of contributed tasks and scripts because they have larger communities.
  • JS developers tend to back away from Groovy/Java tools, even though Gradle is just a DSL.

I strive to build a tool that’s easy to use for many types of developers, yet is as flexible and powerful as I can make it.

The Future

The Gradleware team is working on a ton of features that support JavaScript, and I plan on taking full advantage of them (most of the features are already in the nightly build). Gradle will be able to download JS dependencies just like it does with Java dependencies. It will also have might tighter integration with Rhino.

  • With these new features, I hope to solve JS dependency resolution. I have help from Joshua Newman to include AMD and CommonJS in the next version of the plugin. If you’re interested, you should subscribe to the issues or provide feedback.
  • Testing is another gap I hope to close soon. I have plans to incorporate automated testing via Rhino+QUnit/Jasmine/Other and JSTestDriver.
  • I’d like to give some automatic benefits to projects that adhere to common conventions like folder structure. We can auto-wire source declarations and configure tasks.
  • Finally, source maps is a small but useful and easy-to-implement feature.

If you feel like something is missing, you can always email me or submit an issue on GitHub.

Posted on under gradle