Monthly Archives: February 2013

Getting Started with Grunt JS

If you’re not familiar Grunt (gruntjs.com) is a “task-based command line build tool for JavaScript” along the lines of Ant or Maven for those of you from the Java world.

One big reason I love this tool is no Java is required. This is already a huge plus for me since I don’t like to run Java on my actual development machine for various reasons I won’t get into (maybe another post).

In any case the only dependency you have is that you have to have NodeJS installed. Not a huge deal since you already have it installed right? If you don’t no worries, just head over to nodejs.org and download the latest release.

If you’re on a Windows machine I also recommend that you install the latest version of Git for Windows. Not only do you “get Git” (get it?) which is pure awesome, but you get some of the more useful Linux commands (VIM, grep, etc). The Windows command console will probably work as well, but I have not tested it for this example. The Node installer will also install a NodeJS shortcut that also offers a Node command-line console, this will work as well.

Once you have Node and your command line console you should be able to open up “git bash” (if you’re using git) and then type “node”. If you see the > prompt node is ready to rock (see below)

NPM and Express

Not going into too much detail here as NPM and in particular Express are larger topics that I encourage you to investigate if you’re interested in developing with Node.

The short of it is NodeJS has this thing called NPM (the Node Package Manager) baked into it. If you’re familiar with Nuget on .NET it’s very similar. What NPM does is allow you to install additional packages to Node that other developers have made. For the sake of getting this going I am going to install a default Express project via NPM to work with for this example. (I’m really just scaffolding something for us to look at).

To do this I will first Ctrl+C twice to get back to the $ prompt (or you can close the Git bash window and re-open). Then I’ll install Express globally by typing npm install express -g. Don’t worry, it won’t dump files everywhere. On my machine it created a folder called node_modules in the c:\users\kelly\appdata\Roaming\npm directory.

Now, in your console navigate where you want this project to reside on your file system. Then you’ll type “express test“, with “test” being the directory it will house all your project files in (see below). You’ll also want to follow the on-screen instructions and “cd” into that directory and type npm install which will install all your dependencies for express and node into a folder called node_modules.

Installing Grunt

Installing Grunt is pretty much the same as express. Just type “npm install grunt” and hit enter. I am also going to go ahead and use the –g flag so I can run the grunt keyword via the command line anywhere as well, so type: npm install grunt –g as well.
The final step is to create your gruntfile. I just put mine in the root directory of the project (with package.json and app.js, etc). This gruntfile needs to be named “grunt.js”. So go ahead and create that file (empty for now).

Configuring Grunt

Now the first thing we want to figure out is what we want to build. I’m going to go ahead and create a source directory (test/public/javascripts/src) and then download and dump jQuery, and Underscore javascript files in there. I am also going to go ahead and add a build directory under the javascripts folder as well. This is where my production build output for javascript is going to go. You should now have something like this

So my plan with this structure is to perform some sort of optimization to the jquery.js and underscore.js files and move them into the build directory for the application to reference. The purpose is to reduce the amount of files the browser has to transfer from the server as well as perform any other optimizations like minification (which we will do after this).

The first optimization I’m going to try is to concatenate them together.

Concatenating with Grunt

So in your grunt.js file you’ll need the following:

module.exports = function(grunt) {

    // Project configuration.

    grunt.initConfig({

        concat:{
            dist: {
                src: [' public/javascripts/src/jquery.js', 'public/src/underscore.js'],
                dest: ' public/javascripts/build/mybuild.js'
            }
        } 
    });
// Default task.
grunt.registerTask('default', 'concat');
};

Starting from the top I have a standard NodeJS “module.exports” and function wrapping the configuration. The important bits are inside the initConfig. My first task is “concat”. This keyword is known to Grunt. There are also lint, min, watch, etc to name a few others that are built in (check the grunt site for more details). — UPDATE– Grunt 0.4.0 no longer ships with built-in tasks. Plugins now exists in under the relevant grunt-contrib name. For more detail go here: http://gruntjs.com/plugins

The concat task first expects a name for your task. I called my dist. Then it takes src and dest arguments. The source in this case being an array of files I want to combine. Note that I don’t have to explicitly define the file names. I could’ve just said: ‘public/javascripts/src/*.js’ and Grunt would pick up all the js files in that directory. There are other regexp matches I could do as well if I were inclined. But I will keep this simple.

The next item I have is the destination or dest. This is the path and the file this job will create.

The final thing I need to do is register the task. registerTask takes two arguments. The first is the name of the task (in this case I’m calling it default) and the second is a space delimited list of tasks for that default task (it’s a lot of “tasks” I know).
For this example we’re just using the baked in concat task and I already added that above.

Now all that’s left to do is run the build. Type “grunt” in the command window. You should get something like this (if you don’t check the error and retry):

Magic! It created a new file in the build directory called mybuild.js with underscore and jquery mushed together.

Minifying with Grunt

The last thing I will show you is how to minify. Doing this is as simple as adding the built-in “min” task to the grunt.js file like this:

module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({

        concat: {
            dist: {
                src: ['public/javascripts/src/jquery.js', 'public/src/underscore.js'],
                dest: 'public/javascripts/build/mybuild.js'
            }
        },

        min: {
            dist: {
                src: 'public/javascripts/build/mybuild.js',
                dest: 'public/javascripts/build/mybuild.min.js'
            }
        }
    });

// Default task.
grunt.registerTask('default', 'concat min');

};

Pretty much the exact same configuration as concat. Notice I also added the “min” task to my registerTasks (tasks are run in order of appearance).

Now run this again with “grunt”, it will take a bit longer this time as it’s using the Uglify minifier to minify your concatenated file. You should now have these files with mybuild.min.js being the concatenated and minified version.

Final Thoughts

There is much more you can do with Grunt not only with tasks out of the box, but with packages people have added via NPM. This is a very cool tool that takes the hassle out of having hand craft high performance javascript.
Just grunt!

 

Share and Enjoy