Don't be scared of Grunt!

At Building Blocks, we instill continual improvement in everything we do. A large part of this ethos is about mastering the latest technology, to ensure we're providing the optimum solutions for our clients.  

As part of the Front End team, one such technology that we've fully embraced is Grunt. Here's my advice on how to get started using it...

What is it?

Grunt is a JavaScript task runner. It’s currently the most popular task runner of its kind out there at the moment, and its ever-growing library of plugins means that it’ll be around for a good while.

But what’s a task runner?

A task runner is a workflow tool that can automate the menial, repetitive tasks that you perform in your daily process whilst developing.

Why should I use it?

Task runners take the repetitiveness out of the boring tasks that you may find yourself doing over and over during the front end build of a website.  Once you’ve invested the time in configuring your build process and getting over the learning curve, it’s almost no more effort at all to run these tasks.

Building Blocks use Grunt every day to do things including:

  • Building HTML files from Handlebars templates and JSON
  • Less compilation to CSS
  • CSS minification
  • JavaScript module concatenation
  • L/Hinting JavaScript for errors
  • Create JavaScript documentation
  • Image optimisation

You can ask anybody I work with - I’m an advocate of automating mundane tasks, giving me and my team maximum time to get down to the actual dev work, the bits we enjoy, and the bits that require our expertise.

Amazing, how do I get started?

I’m glad you asked.

Prerequisites

NodeJS. That is all.

Let’s get set up

First, open a command line window and install Grunt and the Grunt command line tools globally:

npm i grunt grunt-cli -g


Note: the i command is short for install and the -g flag installs the Node package globally on your machine.

Next create a directory for your project and enter it:

$ mkdir test && cd test


Now enter  npm init if your project doesn’t already have a package.json file and follow the instructions to set it all up.

Installing Grunt plugins

To install your first plugin (let’s choose cssmin), enter the following command:

npm install grunt-contrib-cssmin -D

Note: the -D flag saves the Grunt plugin to your devDependencies. The -S flag would save the Grunt plugin to your dependencies.

Setting up the task

You’ll need a Gruntfile.js at the root of your projects, in which you should have as a minimum:

	
module.exports = function(grunt) {
    grunt.initConfig({
        // Task configuration goes here
    });

    grunt.registerTask('default', [
        // Tasks registered here
    ]);
};
	

Next you’ll have to load the node module you installed (cssmin) as follows:

grunt.loadNpmTasks('grunt-contrib-cssmin');

In the grunt.initConfig({ }); goes your task configuration objects. An example for the task we installed earlier grunt-contrib-cssmin is as follows:

cssmin: {
    options: {
        banner: 'Built: <%= grunt.template.today("dd/mm/yyyy") %>'
    },
    main: {
        src: 'src/assets/styles/main.css',
        dest: 'dist/assets/styles/main.min.css'
    }
}
	

This task now minifies takes main.css as input and outputs the minified file to your /dist folder.

Run grunt cssmin in the command line window to see the magic happen!

You can also add 'cssmin' to the default task configuration and run grunt in the command line to run this task list.

Now you can automate the minification of your CSS and can even offload this to a build server to be ran automatically after you commit your code. You’ll never have to think about it again!

See a Gist of the entire example Gruntfile.

I’m sold, what next?

The README documents in the majority of Grunt plugins give straightforward examples of the config object required per task, so I’ll leave you to your own devices to scour the plethora of Grunt plugins available and add some to your Gruntfile.js.

Here’s a few of my favourite, essential Grunt plugins:

Bonus round!

Now for some more advanced tips to optimise and tidy up your Gruntfile.

Reusable configuration objects

To enable reuse of file locations, keeping them consistent throughout your Gruntfile and avoiding redundant repetition, add a config object as follows:

config: {
    // Src settings
    src: 'src',
    srcAssets: 'assets',
    // Dist settings
    dist: 'dist',
    distAssets: '_assets',
}

And you can then refer to this in your tasks by using Lo-Dash style delimiters like this:

src: '<%= config.src %>',
dest '<%= config.dist %>'


So if you ever need to change the location it now only needs to be updated in one place!

Reading in external files

You can also read external files such as your .bowerrc, bower.json or package.json to use information about your project in your tasks.

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

And use as follows:

config: {
    bowerDirectory: '<%= bowerrc.directory %>',
    packageJson: '<%= pkg %>'
}
	

Banners

A great way to add dynamically generated content to your distribution files is by the use of a banner. Many plugins such concat allow banners to be added to the top of produced files.

An example of this could be to prepend the build time to your minified CSS file:

// In the config
meta: {
    banner: '/* <%= pkg.name %> :: Latest build: <%= grunt.template.today("dd/mm/yyyy, h:MM:ss TT") %> */\n'
},

// In the task
concat: {
    options: {
        banner: '<%= meta.banner %>'
    }
}
	

In summary

This post served as a short but sweet introduction to the powerful tool that is Grunt, the JavaScript task runner.

Bonus: Here’s a link to my Gruntfile for reference - it’s pretty beasty, so take a long look!

Any questions?

If you need more information or have any questions just get in touch and we'd be happy to answer them for you.