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.

Sigh.

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 WebJars.org 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).

Styling

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.

Conclusions

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:

Comments

Popular posts from this blog

Open source CMS evaluations

I have now seen three more or less serious open source CMS reviews. First guy to hit the field was Matt Raible ( 1 2 3 4 ), ending up with Drupal , Joomla , Magnolia , OpenCms and MeshCMS being runner-ups. Then there is OpenAdvantage that tries out a handful ( Drupal , Exponent CMS , Lenya , Mambo , and Silva ), including Plone which they use for their own site (funny/annoying that the entire site has no RSS-feeds, nor is it possible to comment on the articles), following Matt's approach by exluding many CMS that seem not to fit the criteria. It is somewhat strange that OpenAdvantage cuts away Magnolia because it "Requires J2EE server; difficult to install and configure; more of a framework than CMS", and proceed to include Apache Lenya in the full evaluation. Magnolia does not require a J2EE server. It runs on Tomcat just like Lenya does (maybe it's an idea to bundle Magnolia with Jetty to make it seem more lightweight). I'm still sure that OpenAdvant

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 https://github.com/tfnico/config-mr.git 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: config-atom.git     -> ~/.atom/* config-mr.git     -> ~/.mrconfig     -> ~/.config/mr/* config-tmuxinator.git       -> ~/.tmuxinator/* config-vim.git     -> ~/.vimrc     -> ~/.vim/* config-bin.git        -> ~/bin/* config-git.git               -> ~/.gitconfig config-tmux.git       -> ~/.tmux.conf     config-zsh.git     -> ~/.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 o

Leaving eyeo

Thirteen blog posts later, this one notes my departure from eyeo after 4 years and 3 months. I joined eyeo around the headcount of 80 employees, and now I think there's just over 250 people there. My role coming in was as operations manager, doing a mix of infrastructure engineering and technical project management. I later on took on organizational development to help the company deal with its growing pains . We introduced cross-functional teams, departments (kind of like guilds), new leadership structures, goal-setting frameworks, onboarding processes and career frameworks.  And all of this in a rapidly growing distributed company. I'm proud and happy that for a long time I knew every employee by name and got to meet every single new-hire through training them on company structure and processes.  At some point, we had enough experienced leaders and organizational developers that I could zoom back in on working in one team, consulting them on  Git and continuous integration

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 TeamSp

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 wit