Minify JavaScript using the Google Closure Compiler and Gradle

I have a small Java web application being built with Gradle that includes some custom vanilla JavaScript. I’d like to minify the custom JS code using Google Closure Compiler.

All of the documentation for the Closure Compiler seems to be around using the CLI or the JSON API for minifying JS. I’d much prefer to call the Java API directly from Gradle in e.g. a Copy task.

I’d like to avoid

  • Node solutions
  • Calling out to the CLI and using java -jar
  • HTTP calls to the JSON API

This example is out-of-date and does not reflect the most recent Java API. This question is several years old, though most of the API calls seem similar to the current Java API.

Has anyone else minified JavaScript from Gradle using the Google Closure Compiler Java API directly?

Answer

I have a working solution:

task processWebapp(type: Copy) {
    from('src/main/webapp') {
        include "**/*"
    }
    eachFile {
        if (it.sourceName.endsWith('.js') && !it.sourceName.endsWith('.min.js')) {
            it.exclude()
            Reader reader = it.file.newReader()
            String source = ""
            try {
                source = reader.readLines().join("rn")
            } finally {
                reader.close()
            }

            com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler(System.err)

            CompilerOptions options = new CompilerOptions()
            CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(
                    options)

            SourceFile extern = SourceFile.fromCode("externs.js", "")

            SourceFile input = SourceFile.fromCode(it.sourceName, source)

            compiler.compile(extern, input, options)

            String transpiled = compiler.toSource()

            def directoryPath = it.relativePath - it.sourceName

            File theDir = new File("build/resources/main/${directoryPath}")
            if (!theDir.exists()) {
                theDir.mkdirs()
            }

            PrintWriter writer = new PrintWriter("build/resources/main/${it.relativeSourcePath}", "UTF-8")
            try {
                writer.println(transpiled)
            } finally {
                writer.close()
            }
        }
    }
    destinationDir = file('build/resources/main')
}

This task copies everything from src/main/webapp to build/resources/main while transpiling (minifying) all files ending in .js (but not ending in .min.js) en-route. Gradle then packages and embeds those resources in the resulting jar.

Hope this helps someone else out there using Google Closure Compiler and Gradle.

Leave a Reply

Your email address will not be published. Required fields are marked *