Using Grunt with Java and Maven to Automate JavaScript Tasks
Last updated 16 December 2019
Table of Contents
Grunt is a task runner utility. It’s used to automate various Javascript tasks including minification, obfuscation, and testing. It’s also used to help with other types of static content such as Sass, CSS and even HTML.
In this article, you’ll learn how to use Grunt in a Maven project to minify your Javascript files. With this foundation, you’ll be able to add more Grunt plugins that validate Javascript files, compile Sass to CSS, run Jasmine tests with PhantomJS, and more.
This tutorial assumes you already have a Java project running on Heroku. If you do not, download the Java Grunt example project and deploy it to Heroku by following the Getting Started with Java guide.
Using multiple buildpacks
In order to manage Grunt as a dependency, you’ll need to configure your project to use both the Node.js and Java buildpacks. This is done with the heroku buildpacks
command.
First, add the Node.js and Java buildpacks to your application by running this:
$ heroku buildpacks:add heroku/nodejs
$ heroku buildpacks:add heroku/java
Then confirm the execution order by running this command:
$ heroku buildpacks
=== nameless-brushlands-4859 Buildpack
1. heroku/nodejs
2. heroku/java
In order for the Node.js buildpack to work, it must find a package.json
file in your app. We can also use this file to define the Grunt dependency. Create a package.json
file in the root of your project, and put the following code in it:
{
"name": "java-grunt",
"dependencies": {
"grunt-cli": "0.1.13",
"grunt": "~0.4.5",
"grunt-contrib-uglify": "~0.5.0"
}
}
This defines the grunt-cli
as a primary dependency. It also defines grunt
itself and the grunt-contrib-uglify
module as dependencies. You’ll use these from Maven in a moment.
Now add this file to your Git repository like so:
$ git add package.json
$ git commit -m "added package.json"
On your next deploy, the buildpack will install npm
, which will then install Grunt. But before deploying, you’ll need to configure the Java side of your project.
Calling Grunt from Maven
You can use Grunt from Maven by adding the grunt-maven-plugin to your configuration. This plugin allows you to integrate Grunt tasks into the Maven build process. To add it, open your pom.xml
file and add the follow code to the <project>
element:
<build>
...
<plugins>
...
<plugin>
<groupId>pl.allegro</groupId>
<artifactId>grunt-maven-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<goals>
<goal>npm</goal>
<goal>grunt</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This tells Maven to run the npm
, which will prepare the environment, and grunt
, which will run the automated tasks defined in your Gruntfile.js
. Of course, you’ll need a Gruntfile.js
file in order for this to work. Create the file in the root directory of your project, and add the following code to it:
module.exports = function(grunt) {
grunt.initConfig({
uglify: {
core: {
files: [{
expand: true,
cwd: 'src/main/resources',
src: 'public/js/**/*.js',
dest: "target/classes",
ext: '.min.js'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};
This simple configuration loads the grunt-contrib-uglify module and uses it to convert all of your Javascript files under the src/main/resources/public
directory into Minified Javascript files (i.e. compressed versions of Javascript code) in your target/classes/public/js
directory. The new files will have the extension .min.js
but will have the same basename.
You can reference these files in your applications HTML files like this:
<script src="js/index.min.js"></script>
In the Heroku Java Grunt example, the index.js
file contains this code:
$(function () {
$('body p').append(" and Javascript!");
});
And the index.html file contains this code:
<html>
<head>
<title>Java Grunt Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="js/index.min.js"></script>
</style>
</head>
<body>
<p>Hello from Java Grunt!</p>
</body>
</html>
Now run maven to build the project (you must have npm installed and grunt installed for this to work):
$ mvn clean package
[INFO] Scanning for projects...
...
[INFO] --- grunt-maven-plugin:1.4.1:npm (default) @ java-grunt ---
[INFO] OS Name: Mac OS X
npm WARN package.json java-grunt@ No description
npm WARN package.json java-grunt@ No repository field.
grunt-cli@0.1.13 ../node_modules/grunt-cli
├── nopt@1.0.10 (abbrev@1.0.5)
├── resolve@0.3.1
└── findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
grunt@0.4.5 ../node_modules/grunt
├── which@1.0.8
├── dateformat@1.0.2-1.2.3
├── eventemitter2@0.4.14
├── getobject@0.1.0
├── rimraf@2.2.8
├── colors@0.6.2
├── async@0.1.22
├── hooker@0.2.3
├── grunt-legacy-util@0.2.0
├── nopt@1.0.10 (abbrev@1.0.5)
├── exit@0.1.2
├── minimatch@0.2.14 (sigmund@1.0.0, lru-cache@2.5.0)
├── lodash@0.9.2
├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
├── coffee-script@1.3.3
├── underscore.string@2.2.1
├── iconv-lite@0.2.11
├── findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
├── grunt-legacy-log@0.1.1 (underscore.string@2.3.3, lodash@2.4.1)
└── js-yaml@2.0.5 (argparse@0.1.16, esprima@1.0.4)
grunt-contrib-uglify@0.5.1 ../node_modules/grunt-contrib-uglify
├── chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
├── lodash@2.4.1
├── uglify-js@2.4.16 (uglify-to-browserify@1.0.2, async@0.2.10, optimist@0.3.7, source-map@0.1.34)
└── maxmin@0.2.2 (figures@1.3.5, pretty-bytes@0.1.2, gzip-size@0.2.0)
[INFO]
[INFO] --- grunt-maven-plugin:1.4.1:grunt (default) @ java-grunt ---
[INFO] OS Name: Mac OS X
Running "uglify:core" (uglify) task
Done, without errors.
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.156 s
[INFO] Finished at: 2014-12-11T09:54:44-06:00
[INFO] Final Memory: 23M/227M
[INFO] ------------------------------------------------------------------------
When the process has finished, check the contents of target/classes/public/js/index.min.js
. You find that the Javascript code has been reduced to a single line (it has been “minified”).
Now run the application by executing heroku local
, and open a browser to the index page. You will see the following text:
Hello from Java Grunt! and Javascript!
Finally, add your changes to the Git repo and push your code to Heroku:
$ git add Gruntfile.js pom.xml
$ git commit -m "added grunt task"
$ git push heroku master
...
remote: -----> Fetching custom git buildpack... done
remote: -----> Multipack app detected
remote: -----> Node.js app detected
remote: Installing node modules
...
remote: -----> Fetching custom git buildpack... done
remote: -----> Java app detected
remote: -----> Installing OpenJDK 1.7... done
remote: -----> Installing Maven 3.2.3... done
...
remote: [INFO] --- grunt-maven-plugin:1.4.1:npm (default) @ java-grunt ---
remote: [INFO] OS Name: Linux
...
remote: Running "uglify:core" (uglify) task
remote:
remote: Done, without errors.
...
remote: Verifying deploy... done.
You can view the application by running heroku open
. Your Grunt build has run, and your application is using the minified Javascript files.
Now you can add more modules to your package.json
file, such as grunt-contrib-watch
or grunt-contrib-cssmin
, and those libraries can be used in your Gruntfile.js
configuration. For more information on using Grunt see the Grunt documentation. For more information on using Grunt with Maven see the grunt-maven-plugin documentation.