Skip to main content

Considerations for JavaScript in Modern (2013) Java/Maven Projects

Disclaimer: I'm a Java developer, not a JavaScript developer. This is just what I've picked up the last years plus a little research the last days. It's just a snapshot of my current knowledge and opinions on the day of writing, apt to change over the next weeks/months.

We've gone all modern in our web applications, doing MVC on the client side with AngularJS or Ember, building single-page webapps with REST backends. But how are we managing the growing amount of JavaScript in our application?

Yeoman's logo (not necessarily the conclusion of this blog post)

You ain't in Kansas anymore

So far we've just been doing half-random stuff. We download some version of a library and throw it into our src/main/webapp/js/lib, or we use it from a CDN, which may be down or unreachable when we want to use the application..

Some times the JS is minified, other times it's not. Some times we name the file with version number, other times without. Some times we get the latest library of master branch and name it with the commit-id in the file name, other times we write the commit-id into the top of the included file, or maybe forget about it completely (but please note the source in the commit message at least!). We write CoffeeScript/Typescript that generates JavaScript and we check both files in.


This is a mess. Add to it the mess of just including all JavaScript libraries into the global scope and loading them in random order. 

So, there are some camps out there who are figuring out how to solve this.

There's the Google/GWT/Closure camp, which should be very appealing to Java developers, doing everything "properly" with Maven and Ant plugins. There's also James Ward's which looks promising, but the library coverage is still kind of scrawny.

On the other side, there's the traditional webapp makers, the PHP/Ruby/Node camp(s) which depend on having either of these tools on the command line and using them during development and during the build process. 

My gut feeling is that the latter camp is where the most interesting activity is coming from. These guys have the most experience with hacking and building together tools for easing web development, and they're busier than ever. 

Why not just use Maven plugins and WebJars?

There are plenty of maven plugins for doing JavaScript processing, and you can treat JavaScript libraries as regular runtime dependencies if you want (just overlay them into your webapp).

However, Maven plugins and webjars are regularly far behind the respective Node/Ruby tools because:
  • Maven plugins are tedious to create, so most library devs can't be bothered, and leave it to volunteers from the community.
  • Many library devs don't use Maven anyway.
  • Many library devs are mainly JavaScript developers. Maybe they know a little Ruby or PHP at the most. Probably a lof of them hate Java.
  • The maven plugins use older versions of tools since they are lagging behind. This will be annoying for you as you may have to start patching plugins to get the latest fixes from the JS library in question.
And Maven projects has a tendency to suck things into their tediously slow lifecycle, and depend on the IDE  to speed things up. This works great for some few big languages and libraries, but it's impossible for our IDE's to keep up with the myriad of web development going on out there (although IntelliJ IDEA is doing a fine job of trying).

So, let's run through the various things we want to do with our JavaScript:

Automating tasks, scripting

How do we run the whole build, and trigger other JavaScript processing? We need a scripting tool for automating tasks: copying stuff around, running optimizers, etc. Some place we can call into during the Maven build (using maven-exec-plugin or something like that).

Equivalent in Java land: Ant, Gradle, bash/bat

Solution: Grunt

Alternatives: Pure Node.js? Bash/bat.

Downloading, managing dependencies

Manually downloading JavaScript libraries and upgrading them is a hassle.

Equivalent in Java land: (parts of) Maven, Ivy

Solution: Bower. Based on Node/npm. No central repository, but central registry, uses Git for downloading.

Alternatives: JamJS. Doing it manually.

Managing dependencies at runtime

Since JavaScript has no packages or namespaces, this can get messy quickly, so you need to handle which libraries come into play in which places.

Equivalent in Java land: Maven, packages, classloader fiddling, OSGi

Solution: RequireJS

Alternatives: YepNope. Anything that implements CommonJS or AMD.

JavaScript MVC framework

I'm not sure if that's a good term for it, but the point is to place logic in organized places, and get features like dependency injection and separate your JavaScript from the DOM as much as possible. If you're just working the DOM with JQuery, you're doing it wrong (cause you can't unit-test it).

Equivalent in Java land: Spring MVC, Struts

Solution: AngularJS (from the Google camp) or Ember (from the Rails camp)

Alternatives: Knockout.js, Backbone.js and many others. There's a real framework war going on.

Running unit-tests and web-tests

I haven't researched too much in this direction, as we've just followed the AngularJS recommended choice of the Karma test runner. I like the concept that I can run pure JavaScript unit tests without firing up a browser.

This choice is likely to depend a lot on what other tools you pick. Regarding mocking, I've heard good things about Sinon.js which will work with any testing framework.

Writing JavaScript or generating it

Instead of writing "raw" JavaScript, you stick use the friendly CoffeeScript, the strongly typed TypeScript or the functional ClojureScript. All these transform into JavaScript in the end, although the first two are compiled with Node.

The reason why you should do this is that JavaScript has a lot of sharp edges that can bite you if you don't know the language well.

You could also skip this step and save yourself the extra build-step and level of source-mapping.

Finding the JavaScript source of compressed JavaScript

Make sure you get this right or debugging will be a right pain. The point is to be able to look up where in which source file you are inspecting from your browser, and source maps are the key. There are many tools that can generate source maps for you, but I'm not sure which one I would use yet. Not sure how this applies to CSS (see below).


Now I know this isn't part of JavaScript, but I'll do some notes about CSS here since it's often handled in the same part of the build. You do not want to type CSS manually, as the standard has moved very slow since its inception.

I'm still kind of fresh in this area. There's a CSS-preprocessor called LESS, and there's another one called Sass. Now Sass comes in two different syntaxes: the original .sass (which is kinda whitespace-sensitive stuff), and there's the new .scss which looks a lot more like CSS than Sass does.

There are also some things called Compass and Bourbon, which are both some kind of mixin-managers for Sass, which allow you to not have to deal with vendor-prefixes and other goodness. Both of these are Ruby-based, so

I'd think I'd go for Sass with .scss syntax these days, probably with Bourbon added.

By the way, here's a recent podcast episode from TheChangelog on this subject.

What about Yeoman?

It's somewhat of a starter kit for client-side applications. It features several of the above mentioned technologies in an "opinionated" stack, including Grunt and Bower. I think I'd definitely take this for a spin, as it encompasses the tools I would choose today.


Make sure you are left with a stack that lets you keep a quick roundtrip. Save file, refresh in the browser, change is there.

  • Stick to Node/NPM. Node is supposedly working well cross-platform now. 
  • Grunt is great. Give up on trying to do everything with Maven. 
  • Avoid Ruby? The way I see it I have to drag in Node/NPM at some point anyhow, and if I can then do without managing Ruby versions on my systems, all the better. JRuby via Maven is also an option. (counter-point: Sass, Bourbon and Compass tend towards Ruby)
  • Write pure JavaScript or try out CoffeeScript. I'd say Typescript is a bit too bleeding edge for now (though I may be wrong). ClojureScript is too different from the resulting JS, unless you're using Clojure on the server-side.
  • Frame your JavaScript in a framework like AngularJS or Ember. These have a great ramp-up for getting newcomers started on building single-page applications with tests.
  • Use Sass. With SCSS syntax because that is most similar to normal CSS.

PS: If you enjoy podcasts like I do, I recommend JavaScript Jabbers. A lot of the things above I picked up from a few of their episodes here:


Popular posts from this blog

Managing dot-files with vcsh and myrepos

Say I want to get my dot-files out on a new computer. Here's what I do:

# install vcsh & myrepos via apt/brew/etc
vcsh clone mr
mr update

Done! All dot-files are ready to use and in place. No deploy command, no linking up symlinks to the files. No checking/out in my entire home directory as a Git repository. Yet, all my dot-files are neatly kept in fine-grained repositories, and any changes I make are immediately ready to be committed:

    -> ~/.atom/*

    -> ~/.mrconfig
    -> ~/.config/mr/*

    -> ~/.tmuxinator/*

    -> ~/.vimrc
    -> ~/.vim/*

    -> ~/bin/*

    -> ~/.gitconfig

    -> ~/.tmux.conf    

    -> ~/.zshrc

How can this be? The key here is to use vcsh to keep track of your dot-files, and its partner myrepos/mr for operating on many repositories at the same time.

I discovere…

The End of GitMinutes (my podcast)

I'm just about ship GitMinutes episode 46, which is going to be the final episode. I'll just paste the outro script here, as it sums up the sentimental thoughts pretty well:

I’m happy to have finally finished [publishing the last episodes from Git-Merge 2017], just in time before Git-Merge 2018 takes place in March. I won’t be going there myself, so I’m counting on someone else to pick up the mic there.

It’s sad to be shipping this one as it is probably the last GitMinutes episode ever. To go a bit down memory lane, 6 years ago, my daughter was born, and as I used a little of that paternity leave to set up my podcasting infrastructure and produce the first few episodes. Initially it was just going to be 10 episodes and call the experiment finished. Instead, I got to 46 episodes, the last dozen or so lazily tailing the last few Git-Merge conferences.

To every one of my guests, thank you so much again for coming on to share your passion in this little niche of computer science a…

Using Voice-Chat for Gamers in Distributed Teams

This is a post going into the usefulness of live voice-chat tools in distributed teams.

If you've ever seen the Leeeeeroooooyy Jeeeenkiiins video of World of Warcraft fame, you've heard this kind of tool in action. It's how the participants in the video are speaking with each other - this is not a feature built into the World of Warcraft game - it's a separate team-oriented VoIP software, and it's all about letting gamers communicate orally while gaming. 

Since these tools are for gamers, they have to be
fast (low latency)light (as not to steal CPU-cycles from heavy games graphics) moderate in bandwidth usage (as not to affect the game server connection) There are several options around: TeamSpeak, Ventrilo, more recently the massively grown Discord, and finally Mumble, which is the open-source alternative of the gang.
A few years ago, when I joined eyeo (a distributed company), several of the operations team were avid gamers, and had a TeamSpeak server set up…

Joining eyeo: A Year in Review

It's been well over a year since I joined eyeo. And 'tis the season for yearly reviews, so...

It's been pretty wild. So many times I thought "this stuff really deserves a bloggin", but then it was too inviting to grab onto the next thing and get that rolling.

Instead of taking a deep dive into some topic already, I want to scan through that year in review and think for myself, what were the big things, the important things, the things I achieved, and the things I learned. And then later on, if I ever get around to it, grab one of these topics and elaborate in a dedicated blog-post. Like a bucket-list of the blog posts that I should have written. Here goes:
How given no other structures, silos will grow by themselves This was my initial shock after joining the company. Only a few years after taking off as a startup, the hedges began growing, seemingly almost by themselves, and against the will of the founders. I've worked in silos, and in companies without the…

Working in Teams over Working as Individuals

I recentlypostedthis sketch on Twitter:

Thanks to a few mighty retweets, it gathered a lot of views (9000 impressions, whatever that means). While that's fun and all, I still felt a bit sad that such an awfully simple insight can garner much more popularity than a thorough blog post that I put some hours into.

So, rather than let Twitter get away with this, I'll steal my own content back into the blog :)

The thread went like this:

Pondering how to battle individualism in companies. For some, it is counter-intuitive that teams can be more responsive, faster and even more accountable than single individuals.

Having "teams" in place is no guarantee that team work is happening. Be wary of too large teams, "I/me/mine", personal contact details instead of team point of contact. Good team is sailing crew, not galley slaves.

Beware heroes, go-to persons, calling in favors and other shadow handling of work. Real teams make the work explicit, both requests/needs and re…