The 80-20 Guide to Grunt

This is the beginning of a series of posts on popular web development tools. With the number of tools that developers use now, it’s impossible to be an expert in all of them, and getting started can seem daunting, so I’ll be going over the basics, so you can start right away.

What is Grunt?

Grunt is a JavaScript task runner. Basically, it can automate some boring and repetitive stuff that you find yourself doing often.

Why grunt?

Let’s say you’ve started using Sass. You’ll need to build your stylesheets into CSS files whenever they are changed. There are a few ways you can do this.

The most obvious solution is to run sass source.scss dest.css every time you change the file. You’ll have to run the command every time you modify your .scss files. Clearly, not something you want to do every time you edit your stylesheets.

Improving on the last option, you can run sass --watch source.scss:dest.css. This will watch your .scss file for changes, and generate your CSS files when they’re changed.

How can this be improved? Well, if your only task is running Sass, the second option is perfectly fine. The problems come about when you add more tasks. You may want to run UglifyJS on your JavaScript files. Now you have another command to remember, and you have to run this every time since there’s no watch option. You may want to run JSHint before UglifyJS, wire your Bower dependencies, add prefixes to your CSS, minify your HTML, and insert a LiveReload script into every HTML file. That would be a nightmare to do every time you changed some files.

A simple Gruntfile

A Gruntfile is just a file named Gruntfile.js that Grunt will look for when it is run. Here’s a Gruntfile that will accomplish the same as sass source.scss dest.css :

Line 1 is how every Gruntfile will start. Basically, this file exports a function which takes one parameter, an object named grunt. grunt.initConfig() is a function which takes an object. This object is a hierarchy of tasks, targets, and files/options.

Don’t worry about how to run this Gruntfile yet, that’s coming.

The Grunt Hierarchy

The only task declared in our sample Gruntfile is sass. The only target in the sass task is build. build is what we have called the target that compiles source.scss to dest.css, but we could have called it dist, preprocess, or kitten.

Targets are declared inside of tasks. You can reference the target with a colon after the task, ex. 'sass:build' will reference the build target we have declared in the sass task.

Inside of targets is where you declare what files to watch, and any other parameters that a task requires. In this case, we’re declaring the files as a dictionary, where each key is the destination file, and each key’s property is its corresponding source file.

Using the Gruntfile

To use this Gruntfile, you’ll have to install grunt-contrib-sass using npm. Run npm install grunt-contrib-sass. This is a plugin for Grunt which is really just a wrapper around Sass itself. After that, you just run the following command to run the build target:

You can also run the following, which is equivalent:

This tells grunt to run all targets of the sass command, which in this case is only build.

More tasks and watching files

Here’s a Gruntfile which compiles Jade and Sass files:

There’s really not much new here, except now you can compile your jade file by running grunt jade. But really you’re in the same situation as before, having to manually run the commands whenever you change the file. This is where grunt-contrib-watch comes in. We’ll create a new task, called watch, and it will watch for changes in our files. Here’s the watch task, which can be added right after the jade task:

Watch tasks are simple, you give it the files to watch, and the tasks to call when those files are modified. As you can see, you can specify a task and target, or just a task.

Now, you can run grunt watch, and your Jade task will be run when index.jade is modified, and your Sass task will be run when source.scss is modified.

Combining tasks

Using the previous Gruntfile, and the added watch task, we could run the following to compile our Sass files, then compile our Jade files, then watch for changes:

Of course, you don’t want to do this every time. This is where registering tasks comes in. Add the following line after the initConfig function, and after loading npm tasks:

This will tell Grunt that the task doItAll should run sass, then jade, then watch. After that you can call it like any other task:

Options

This is the last bit you need to be reasonably proficient with Grunt. Options are exactly what they sound like. They let you configure tasks or targets. For example, here’s a Gruntfile to build sass files:

Each plugin for Grunt will have its own set of options, which you’ll need to look in the docs for. Options can also be specified for a task, instead of a target, and will apply to all targets of that task. If task options and target options conflict, the target option will be applied.

return 0

Hopefully that gave you an understanding of the basics. If you have any questions, feel I missed something, or anything else, leave a comment below.

Extra 20%

We’ve only used two ways of declaring files for a target, an array of files:

And a dictionary of files:

There are quite a few ways to declare source and destination files in Grunt, and they’re all covered here. Understanding these will help greatly when creating more complex tasks.

Leave a Reply

Your email address will not be published. Required fields are marked *