Posted on by & filed under javascript, programming.

What I Needed It For

Some of my friends and I occasionally get together to play a pencil-and-paper role-playing game called Anima: Beyond Fantasy. This game has a really rich set of rules for creating the characters who inhabit the imaginary world in which the game’s story takes place. You can create just about any kind of warrior, martial artist, wizard, rogue, psychic, and so forth that you can think of from your favorite shows or books, complete with rules on how all of their abilities work in the game. But this flexibility comes at the cost of a pretty darn complicated character generation system; some abilities depend on having other ones first, there are limits on how much you can develop one ability in relation to others, and each character has a limited pool of “points” (of several different types) to be spent acquiring those abilities. Defining all the major characters in the story well enough to run them in the game turned out to be pretty time-consuming. Being a programmer, I figured this was nothing that a good piece of software couldn’t fix, and set about writing a character generation utility using a language (JavaScript) and a few libraries (jQuery, RequireJS, Twitter Bootstrap) that I wanted to get more experience with. About 18 months of occasional coding in my free time later, I had a mostly finished program…and quite a few JavaScript files. I’d kept the code fairly well organized, but now I wanted a nice automated process for generating an optimized version of the app that I could put online for other people to try out. Often for a project like this you’d use tools appropriate for whatever server-side web application stack you’re using, but this is a purely client application that runs completely in the browser as a single web page. I’d heard that people were using Grunt as a JavaScript build tool, so I decided to try that out.

Getting Started with Grunt

Grunt describes itself as a “task runner”; it’s basically a task definition and execution framework like make, ant, and rake —to name a few which are commonly used with other programming languages. It’s implemented in JavaScript itself, using the Node.js framework, so you need to install Node first in order to use it (this is becoming increasingly common for JavaScript-related utilities). Once that’s done, you use the Node.js package manager (npm) to install Grunt’s command line interface:

npm install -g grunt-cli

This basically just puts the “grunt” executable in your path, so you can run it in a project directory to execute Grunt tasks; it looks for the actual Grunt library inside whatever project directory you run it in. To be able to do that, we first need to make it look like a project directory. For Node.js to recognize it as such, we need a package.json file in the project’s root directory. For my character generation utility, it started out like this:

  "name": "anima-character-generator",
  "version": "0.5.0",
  "description": "A character generation utility for the Anima: Beyond Fantasy RPG",
  "homepage": "",
  "keywords": [
  "bugs": "",
  "repository": {
    "type": "git",
    "url": ""
  "devDependencies": {}

With that done, we can start installing Grunt and its plugins into the project directory. (These all get installed into a node_modules folder which you can add to your .gitignore file or whatever other mechanism your version control system uses to specify files and directories that shouldn’t be checked in.) For Grunt itself:

npm install grunt --save-dev

That last parameter tells npm to automatically add the library you just installed to the list of development dependencies for your project (basically, stuff you probably need when working on the code but not necessarily when just running it). So the “devDependencies” section of packages.json has now been updated to look like:

  "devDependencies": {
    "grunt": "~0.4.0"

With that in place, other people who check out your code have a somewhat easier time getting things set up. They still need to install Node.js and grunt-cli as I described above, but to get Grunt and any other plugins for it you install later, they’ll just have to run “npm install” in the directory which has package.json in it.

Making Grunt Useful

Now that you have Grunt set up, you need to tell it what you want it to do. But Grunt itself really doesn’t know how to do all that much; it’s the huge selection of plugins for different kinds of tasks that really make this utility useful. So let’s install one of those first. I said I wanted to optimize my JavaScript files for deployment; I’m using RequireJS, so mainly I just need a plugin that’ll run that library’s r.js optimizer for me. Oh look, there is one:

npm install grunt-contrib-requirejs --save-dev

(Note that there are actually several Grunt plugins for RequireJS available. In cases like this where you need to pick one, the grunt-contrib-* plugins are usually a good default choice when available.)

The actual task definitions go into a Gruntfile.js (or, for CoffeeScript) file. To run my optimization task the way I want to, I need one that looks like this:

/*global module: false, require: false */
module.exports = function (grunt) {

    // Project configuration.
        pkg: grunt.file.readJSON('package.json'),
        requirejs: {
            compile: {
                options: {
                    baseUrl: './js',
                    findNestedDependencies: true,
                    logLevel: 3,
                    mainConfigFile: './js/config.js',
                    name: 'libs/almond',
                    include: 'main',
                    optimize: 'uglify2',
                    optimizeCss: 'none',
                    out: './build/js/main.js',
                    wrap: true


    grunt.registerTask('default', ['requirejs']);

With this in place, I can type “grunt requirejs” (or just “grunt”, since I registered requirejs as the default task) and it will run r.js for me with the appropriate settings to concatenate all the JavaScript files ultimately used by my “main.js” script into a single file, replace the RequireJS loader with the lightweight almond loader (since I no longer need to load code from other files), minify the result with UglifyJS2, and finally create the generated file at the location specified by the “out” parameter. Note that I didn’t need to explicitly download r.js, write a shell or batch script to run it, create an “” configuration file just to define the build, or a few other tedious things I otherwise would have needed to do. And the best part is that with this framework in place, defining new tasks becomes trivially easy and doesn’t involve adding any more new files to the project (we’ve only created two new files that actually get checked into version control). For example, if I want to generate HTML documentation for the JavaScript API from my JSDoc comments in the source code:

npm-install grunt-jsdoc --save-dev

And in Gruntfile.js:

        jsdoc: {
            all: {
                src: ['js/*.js'],
                dest: 'doc'
        requirejs: {


Or to check all the JavaScript code (including Gruntfile.js itself) for common errors using JSHint:

npm-install grunt-contrib-jshint --save-dev
        jshint: {
            all: ['Gruntfile.js', 'js/*.js'],
            options: {
                bitwise: true,
                curly: true,
                eqeqeq: true,
                forin: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                noempty: true,
                nonew: true,
                onevar: true,
                regexp: true,
                trailing: true,
                undef: true,
                unused: true,
                white: true


These can then be run from the command line via “grunt jsdoc” or “grunt jshint”. The latter in particular I find extremely useful by making it trivially easy to check for and fix simple mistakes before even trying the code in the browser.

A Few Hours Later

In about 4-5 hours, I went from only having a vague understanding of what Grunt was to having a working Gruntfile.js that checked my code for errors, generated my documentation, concatenated and minifed my CSS and JavaScript files, renamed those generated files with MD5 hashes to avoid cache problems, and created a copy of the HTML page modified to work with those minified files (you can see the full file here). Granted, I already had scripts to run JSHint for a single file and to generate JSDoc output, and was pretty familiar with how r.js works. But using Grunt really did simplify the configuration and made it easier to run everything.

Oh, and if you’re curious about what that character generator looks like in action, you can find it online here.


One Response to “Taming JavaScript with Grunt”

  1. Brian

    I really like your tool, and your write up is pretty good as well. I actually found this blog because I found and started using the character generator. I was wondering if you had noticed, or had time to fix yet, the bug with importing that replaces Nephilim (and possibly other) races with “Other”, which removes the racial modifiers on import.

    Keep doing side projects like this. It’s this kind of thing that is inspiring me to continue my own technical education. Thanks :}