Front-end Automation with Grunt – Part One

In the past, as a Front-end Developer, you had to have a fairly high tolerance for repetition.  Our job typically entailed performing similar small tasks again and again, such as typing out the same selector names in CSS, opening and re-saving sprites as they grew in size, converting SVG files into PNG files, and so on.  These time-consuming jobs got tiring quickly.

Nowadays, many of us are using Sass or Less  to handle some of these shortcomings of CSS. We sometimes even use Compass to extend Sass with pre-defined ‘mixins’ and spriting capabilities – but this automation is still limited to our CSS and images.

Introducing Grunt

Simply put, Grunt is a JavaScript task runner that deals with all those repeatable tasks that every project has.  I’ve been using it to do the same tasks I used Sass and Compass for, but I’ve also been throwing in minification of JS files, JS linting, browser live reloading and image conversion from SVG to PNG. There are over 2000 plugins you can add to Grunt. So, if there’s a task you perform regularly, there’s a good chance a Grunt plugin already exists for it.

Setting up a Project

You’ll need node.js installed on your system to get started, then use the node package manager (npm) to install Grunt and other Grunt plugins.  Rather than regurgitate the docs fully, you’re best off looking here for full details on how to do this: http://gruntjs.com/getting-started.

Once you have node.js installed, go to your root directory in Terminal and type:

1
sudo npm install -g grunt-cli

This will install the command line interface for Grunt, allowing you to use the grunt command. You may need to run as sudo or Administrator.

When setting up a new project you need to create a ‘package.json‘ file in your root.  The simplest way to do this is to run the command below. It’ll ask you to specify a few things such as a ‘project name’, ‘author name’ etc., but you can skip most of the steps by leaving them blank.

1
npm init

If you weren’t starting from scratch and the project already has a ‘package.json‘ you would run the below instead to make sure all dependencies were downloaded:

1
npm install

Once you have this you can install the Grunt dependency.

1
npm install grunt --save-dev

This will download Grunt via npm and add it to your  ‘package.json’ file as a dependency.  Omitting the –save-dev part will install the package but not list the package as a dependency in the  ‘package.json’ file.   You should now have a node_modules folder in your root and an entry for Grunt in your ‘package.json‘ file.

Next create a Gruntfile.js file in the root and add the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Gruntfile.js */
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
   pkg: grunt.file.readJSON('package.json'),
   // Tasks to go below here
});
// Load plugins here
// Default task(s).
grunt.registerTask('default', []);
};

Now, if you type ‘Grunt’ into the Terminal and get ‘Done without errors’ you know it’s set up correctly.  Although you haven’t set up any tasks yet, running this will let you do so as we’ve now got everything set up ready to go.

Getting Grunt to do our pre-processing

Normally, we’d use Compass to watch and compile our Sass files. So let’s set that up first.  The Grunt Compass plugin can be found here https://npmjs.org/package/grunt-contrib-compass

With terminal open at your projects root, install the package via npm:

1
npm install grunt-contrib-compass --save-dev

Include the plugin in ‘Gruntfile.js’ by adding the following line underneath the ‘Load plugins here’ comment:

1
2
// Load plugins here
grunt.loadNpmTasks('grunt-contrib-compass');

You’ll then need to add the compass task and any options to the config section and state compass as a task to run when you type ‘grunt’ into the terminal…so your ‘Gruntfile.js‘ should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* Gruntfile.js */
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    compass: {
        dev: {
            options: {
               /* Either use your config.rb for settings, or state them here */
               //config: 'config.rb'
               require:['susy'],
               httpPath:"/",
               sassDir:"site/assets/stylesheets/src",
               cssDir:"site/assets/stylesheets/build",
               imagesDir:"site/assets/images",
               javascriptsDir:"site/assets/js",
               fontsDir:"site/assets/fonts",
               outputStyle:"compact",
               noLineComments:true,
               relativeAssets:true,
               raw: "preferred_syntax = :sass\n"
            }
        }
     },
});
// Load plugins here
grunt.loadNpmTasks('grunt-contrib-compass');
// Default task(s).
grunt.registerTask('default', ['compass']);
};

The only registered task we have at the moment is the default task – what runs when we simply type ‘grunt’ into the Terminal.  So in this case it will run the ‘compass’ task.

Getting grunt to watch files

At the minute we have to type ‘grunt’ in Terminal to perform this task, which isn’t really effective for pre-processing CSS.  We’ll want to watch for changes to our files and perform the ‘compass’ task automatically when any Sass file changes.

The setup for watching files is very similar to what we just did for setting up compass (https://npmjs.org/package/grunt-contrib-watch).  Install the plugin:

1
npm install grunt-contrib-watch --save-dev

Then add any configuration settings needed for the plugin (see its docs) and load the plugin after like we did for the Compass plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* Gruntfile.js ...continued */
.
.
.
    compass: {
        ...
    },
    watch: {
        styles: {
            files: ['site/assets/stylesheets/src/**/*.scss',],
            tasks: ['compass'],
            options: {
                spawn: false,
            },
        },
    }
});
// Load plugins here
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['compass']);
grunt.registerTask('dev', ['watch']);
};

Here, I’ve setup a new registered task called ‘dev’.   I’m going to use this task to initiate everything I want to happen when I’m working on a project – starting with running the ‘watch’ task.  So I’d type the following to start this registered task.

1
grunt dev

You should now have Grunt watching any Sass files and pre-process them once you save.

In the next part we’ll look at other useful Grunt plugins including automatically converting your SVG images to PNGs.