Introduction

Imagine you want to build an application with a Java or Clojure backend, exposing services via REST. The services are consumed by a JavaScript application using AngularJS.

In article, I summarize the experience I made to develop, test, build and release applications with mixed technologies. I will give you an introduction into JavaScript tooling and share my experience how to integrate the GUI with a Java or Clojure backend.

JavaScript build tool ecosystem

The JavaScript ecosystem is amazing. You will find well designed tools, each one with a defined but limited responsibility, which allows to combine them into powerful tool chains. It is enlightening coming from a Java Maven background. The Java world has a tendency to create things like ‘the coffee making, water distributing, ice machine, soap bubble making bicycle’.

Task runner

A task runner can execute tasks, define dependencies between them, run them in parallel or sequential but very important they don’t know much about the tasks themselves. Gulp Grunt and Brunch fall into this category.

Combined with plugins the task runner can do anything you need to do with a JavaScript web application.

Here is an extract of a task definition using Gulp. It compiles Sass style sheets into normal CSS and send a desktop notification, if it succeeds or fails.

	// load plugins
	var gulp = require('gulp'),
    	minifycss = require('gulp-minify-css'),
    	notify = require('gulp-notify'),
    	source = require('vinyl-source-stream'),
    	streamify = require('gulp-streamify'),
    	uglify = require('gulp-uglify'),
    	sass = require('gulp-ruby-sass');

	// define a task	
	gulp.task('styles-sass', function () {
	    return gulp.src(paths.styles_sass)
	            .pipe(sass({ style: 'expanded' }))
	            .on("error", notify.onError(function (error) {
	                return "CSS problem: " + error.message;
	            }))
	            .pipe(gulp.dest('dist/dev/styles'))
	            .pipe(notify({ message: 'Saas styles task complete' }));
	});	

A typical JavaScript build file consists of small tasks. Whenever you need to achieve something, just search for a plugin using something like “Grunt minify CSS” or “Gulp compress JavaScript”.

To describe the three task executors shortly: Grunt has the largest plugin collection, Gulp is more efficient has it uses pipes to pass the output from one step into the next, Brunch is the youngest and makes heavy use of conventions over configurations, which makes it very easy to setup but on the other hand sometimes harder to understand and to adapt. After trying out each of them, I choose Gulp. But this is a matter of personal preferences. Each tool has its shiny sites.

Dependency management

The Maven or Clojars equivalent in the JavaScript world are NPM and Bower. Both help dealing with fetching dependencies. NPM provides dependencies in a format suitable for JavaScript backend application. Combined with a tool like Browserify which packs the dependency into a single file, it can be used for JavaScript in the browser as well. Bower is already intended to be used with Browser applications. Both are viable solutions.

You will probably always use NPM to install all other tools needed for development.

Writing JavaScript modules is not trivial, as you need to target both NPM and Bower. It is worth to invest some time understanding how they work. Especially in larger GUI applications you need a form of modularization to avoid naming conflicts.

Scaffolding

There is a good chance that you run into Yeoman as well. It helps to quickly start building a JavaScript application. If you want to have an AngularJS application including build script, test runner and an application template, just type:

yeoman init angular

Alternatively, there is large choice of boilerplate tempates.

Development

For development there is a list of typical tasks for a JavaScript application.

All this can be achieved with plugins for Gulp, Grunt or Brunch. The automated test execution, reloading and quality check are very useful. Every time you save a file, you get a feedback fractions of a second later.

To get an impression, how to configure such a build file, I found it helpful to develop it step by step from scratch and then compare it to existing solutions.

Next thing is how to integrate the JavaScript GUI with a deployed Java or Clojure backend.

A very good way to achieve this is using a JavaScript web server with integrated proxy. It is a normal web server serving requests from a defined directory. In addition a URL like /api can be defined to be forwarded to a backend running under its own port.

Why not using backend tools to build the JavaScript application?

Gradle and even Maven has extensions to build JavaScript applications. The answer is simple. If you go swimming what do you pick: flippers or a bucket of heavy stones.

The JavaScript build tools are much more advanced, used by many more people and are very easy to adapt to your own needs.

Packaging for Production

For production CSS, JavaScript and libraries needs to be minimized. If the backend and the GUI is packaged as single application, the JavaScript application is copied into the web directories of the backend project.

In the past, I achieved this by adding a task to the Gulp or Grunt build. The reason, I am controlling this from the JavaScript and not the backend build script, is that the JavaScript task runners are way easier to adapt. Neither of tools like Maven or Gradle (Java world) or leiningen (Clojure world) is as flexible.

Releasing

Typical tasks to release a project are

I found this part a bit tricky. Releasing can be both controlled from the task runner and the backend build script or even a third script controlling both. I used the backend build script in the past to do the actual release, but triggered the JavaScript task runner before doing this from an outside script.

Other solution, I encountered:

Summary

This overview should get you started easier in building mixed builds. Feel free to sent me comments with your own experiences.