Automate Recurring Tasks with Grunt.js

Catherine Farman
Share

I’m a recent convert to using Grunt.js to run tasks that are an essential part of my development workflow. Grunt is a command-line tool that lets you run a heap of tasks in one command, all customized to your liking and tailored to your project’s needs. It helps me automate repetitive jobs like CSS preprocessing, or minifying code for a production environment.

After moving to Grunt in a team environment at Happy Cog, it’s helped us solve new problems that we didn’t even foresee using it for, like image optimization, database syncing, and WordPress theme management. Read on to learn how to automate front-end Sass and JavaScript tasks with Grunt, and how to get your project using it in no time.

Pick a Task

Grunt’s community of developers mean there’s a plugin for most any task you’d like to perform and automate. Yet I’ve found that the easiest way to get started with Grunt is to pick one or two essential processes you want to automate, and get those running on your project. As a front end developer, my most crucial tasks are Sass compilation and JavaScript concatenation. This article assumes you have Sass 3.3 installed. To create a practice directory, download or clone my grunt-js-base project to your machine and check out index.html in the browser.

As it happens, the Grunt.js plugin repository lists two officially maintained plugins that will serve these purposes: Uglify for JS minification (and more), and grunt-contrib-sass.

Install Node.js and Grunt’s Command Line Interface

Before we can install these plugins, we need Node.js on our computer. Luckily, it’s an easy install for Windows or Mac OS. Just go to nodejs.org and click the big green INSTALL button to download.

Once you’ve installed Node.js, you need Grunt’s Command Line Interface tools on your computer. From a terminal window, run npm install -g grunt-cli. If you get a permissions error, I suggest reading this article on npm. This article, written by Isaac Schlueter, will teach you how to install modules without using sudo.

Add package.json to Your Project

You need two files for every project that uses Grunt – package.json and Gruntfile.js. Start by adding package.json to your project folder, in the root. You can use the basic contents from the Grunt.js setup instructions, substituting with your project’s info. With time you’ll evolve your own starter kit for projects. Here’s my default Grunt project‘s package.json:

{
  "name": "grunt-js-base",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-uglify": "~0.2.2",
    "matchdep": "*"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/cfarm/grunt-js-base.git"
  },
  "author": "Catherine Farman",
  "homepage": "http://cfarman.com"
}

As you can see, a package.json file is a set of JSON objects and properties that describe the packages for your project. The most important part of this file that will change as you add plugins to your project is the devDependencies object. The properties defined here are all the modules necessary for your project to be developed and tested. In our case, so far we have the Grunt module itself, the Uglify plugin, and a module called matchdep, which we’ll explore in a moment.

Every time you add a new plugin to your project, you’ll update this devDependencies list with the plugin name and the version number. For now, save the above file in your project’s root folder to get started.

Add Gruntfile.js to Your Project

Along with package.json, you need to add a Gruntfile to the root of your project. My default Gruntfile looks like this. Again, this is just a set of JSON objects and properties that we will customize to set up our tasks to run however we’d like. Most of your Grunt configuration will take place in this file.

Save Setup Time with the matchdep Plugin

Notice the second line of my Gruntfile has the following special instruction:

require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);

This instruction invokes the matchdep module to make it easier to install new plugins for my projects. Whenever you add a new task, you usually have to install the Node module for your project, then add a line to your project’s Gruntfile to load the task. With this line above and the matchdep plugin installed, you can skip that step whenever you add a new plugin to your project, saving setup time.

Install Plugins for Your Project

Though the Sass and Uglify plugins we’ll be using are listed in package.json, we need to take another step to actually install them on our computer. Navigate to the project directory on the command line and run npm install to get these modules added to your project. A successful install will look something like this:

npm install Output

Notice that a new folder has been created in your project root called node_modules – all the plugin dependencies live here.

The grunt Command

Now for the moment of truth! Run the following command (inside your project directory still):

grunt

Your terminal should look like this:

Terminal Output

And if you’re using my starter grunt project, you can check out index.html in your browser to see that Grunt has run its task, compiling your Sass to CSS and uglifying your JavaScript:

Grunt Status 2014-05-02 15.10.17

If you get any syntax errors, Grunt will tell you which line to fix. Once you’re ready to try again you’ll hit Ctrl+C to quit watching and run grunt again to run your tasks.

Anatomy of a Gruntfile

If you’re curious what’s going on with Grunt, take a look at Gruntfile.js to see how our tasks are defined.

sass: {
  options: {
    precision: 5
  },
  dev: {
    options: {
      style: 'nested', // compact, compressed, nested or expanded
      sourcemap: true
    },
    files: {
      'stylesheets/css/styles.css' : 'stylesheets/scss/styles.scss'
    }
  },
  prod: {
    files: {
      'stylesheets/css/styles.css' : 'stylesheets/scss/styles.scss'
    }
  }
},

Inside Grunt’s initConfig section we’re setting creating our task objects. For both Sass and Uglify, I’m setting up two different tasks: a default task that runs when the grunt command is invoked, and a production task that runs under grunt production. The options are different for each to reflect a local development environment’s needs versus the finalized output for a production website.

Try running grunt production and then look at your output files, script.min.js and styles.css. Compare them to the output created by the default grunt task to see the difference.

Conclusion

There’s a whole world of Grunt plugins out there, and lots of problems they can solve for you as you’re building your projects. Search for tasks at http://gruntjs.com/plugins. Once you find a plugin that interests you, use npm install to add the module to your computer. And, don’t forget to add the plugin to your package.json file. Once it’s installed and listed in package.json, you’ll need to add task options to Gruntfile.js. Finally, at the bottom of Gruntfile.js, add your task’s command to either the development task, production task, or both to make it available as a grunt task.

You can also add tasks to your Watch tasks in Gruntfile.js if you want to watch for changes to files that trigger the task to run (useful for front end changes). This will keep the Grunt task running in your terminal and files will compile whenever you save them, so you don’t have to run the grunt command more than once while you’re working.

Now that you’re automating your common tasks in Grunt, you’ll find your workflow improving enormously.