Development workflows with Grunt

February 13, 2014 Paul Meskers

After working in one technology stack for a while, it is easy to become reliant on a toolchain you know and love. However, there are times when other toolchains are better suited to solve a problem at hand. I’d like to provide a brief overview of Grunt and how valuable it is as a front-end development tool.

What is Grunt?

For the uninitiated, Grunt is a task runner built in JavaScript. The tasks it can run are provided by a plethora of community supported plugins, which can be combined ad hoc to perform a wide variety of tasks typically associated with front end development. These plugins come in the form of node modules (managed via [npm](, and are installed as dependencies for either production or development use.

Developers coming from Rails may notice a number of parallels to Rake and Rake tasks. Similar to how one might use Rake to migrate databases or run tests, Grunt offers plugins that compile stylesheets and minify your code. For a Ruby developer, bundler groups can be used to define when certain dependencies need to be installed, such as whether a library is development only or necessary for production. Npm offers the same affordances when managing what modules it needs to pull in.

To help elucidate what type of things you can use Grunt for, let’s take a look at a few of the commonly used tasks available to Grunt –

grunt-contrib-compass: Compile stylesheets written in sass/scss to css.

grunt-contrib-watch: Watch for changes in a set of files, and when they are changed, perform a specified task.

grunt-contrib-connect: Runs a static web server.

Hopefully you can start to see how you can combine these several small pieces into a powerful tool that compiles all your stylesheets, minifies your JS, live reloads your browser, and maybe one day folds your laundry (For more great examples, check out the grunt-contrib repository).

Why Grunt?

We all love Ruby, but not every project calls for a Ruby-based toolchain. Building static web pages (e.g., any client-side application that uses an API for all its services), Node.js projects, and Java projects all benefit from a robust set of frontend tools when building modern web apps.

Additionally, the Grunt community is maturing and producing lots of high-value plugins that help tackle complexities of development and deployment across many different technology stacks. And learning another tool to keep in your belt is always a positive thing to have when approaching new problems or revisiting old ones.

Basic example

With that said, let’s take a quick and practical look at what goes into using Grunt. Additionally, the official Grunt.js Getting Started guide is an excellent read with links to further reading.

As a pre-requisite, you’ll need to have node and grunt-cli installed on your machine:

brew install node
npm install -g grunt-cli

Using npm to manage your project dependencies means you’ll need a package.json which details your project information and dependencies. Here’s a sample one:

  "name": "my-project-name",
  "description": "It's great!",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x"
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-jshint": "~0.8.0",
    "grunt-express-server": "~0.4.11",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-contrib-compass": "~0.7.0",
    "grunt-contrib-uglify": "~0.2.7",
    "grunt-contrib-copy": "~0.5.0"

The file is simply a JSON object, and an interesting piece to notice is the dependencies and devDependencies. These two objects specify which packages should only be installed in a development environment, and which are needed as a project dependency.

You’ll also notice Grunt itself is a dev dependency. What we installed earlier was the Grunt command line interface. In order for Grunt to function in a project, the project must have a locally installed grunt package, as well as our next important piece: the Gruntfile.js:

module.exports = function(grunt) {

    pkg: grunt.file.readJSON('package.json'),

    compass: {
      dev: {
        options: {
          sassDir: 'src/stylesheets',
          cssPath: 'web/public/css'

    jshint: {
      files: ['src/javascript/main.js']

  grunt.registerTask('default', ['compass', 'jshint']);

The first bit of this file is boilerplate — it simply opens up our local Grunt for task configuration and points out the local package.json from earlier.

The first important step is the configuration of the compass plugin, which specifies where the sass stylesheets are located, and to what destination they should be compiled. We additionally tell JSHint what files to run against. Next, we make sure grunt loads the grunt-contrib-compass and grunt-contrib-jshint packages from npm in order to add the tasks to our Grunt. Lastly, we register a custom task (default, in this case) to run compass and jshint in one step.

And that’s it! Just by running grunt from the command line now, the default task will run and compile our stylesheets and JSHint our JavaScript files.

So much more

This introduction is really just scratching the surface of what Grunt can be used for, but hopefully it has whetted your appetite for more. Additionally, for those used to different toolchains and technology stacks, hopefully this has cast a light on what other options are out there. If you’re looking to introduce Grunt into your current project, you can start with something as simple as a task which watches your JavaScript files and runs JSHint along with your JS unit tests every time a file changes. Even a simple use case like this can provide a great deal of value when developing for the front-end.

About the Author


Have you tested your tests lately?
Have you tested your tests lately?

Summary: If you are using the rspec_api_documentation gem to test and document your API, you can use this c...

EMC Q&A Part 2: How Spring and tc Server Reduce Costs and Improve Productivity
EMC Q&A Part 2: How Spring and tc Server Reduce Costs and Improve Productivity

How did EMC reduce costs and increase productivity with Spring? This article is part two of our Q&A session...

SpringOne 2021

Register Now