Sharing the Code

Programming stuff that might be useful to others

Introduction to Grunt

Grunt is a build system for client-side development. Up to now I’ve been using separate terminal windows to compile my Sass and CoffeeScript. Grunt allows you to do that in one command:

grunt watch

It also supports LiveReload so you don’t have to keep pressing the refresh button. You can also use it to deploy to a production server by using some Grunt plug-ins.

Grunt requires Node.js and once you’ve got Node installed you can install Grunt with:

npm install -g grunt-cli

You will need to be logged in as root.

package.json

Grunt requires 2 files in your project – package.json and Gruntfile.js. package.json contains the project’s dependencies but I also put general project properties in here also that are then used in Gruntfile.js. Gruntfile.js is where you configure the tasks. You can create a basic package.json by typing:

npm init

Or you could start with the example below:

[sourcecode language=”javascript”]
{
“name”: “my_theme”,
“version”: “1.0.0”,
“dependencies”: {},
“devDependencies”: {
“grunt”: “~0.4.0”,
“grunt-contrib-watch”: “~0.4.3”,
“grunt-contrib-compass”: “~0.2.0”,
“grunt-contrib-uglify”: “~0.2.0”,
“grunt-contrib-coffee”: “~0.7.0”
},
“engines”: {
“node”: “>=0.8.0”
},
// User-defined properties
“coffeeScriptFile”: “my-theme-behaviors.coffee”
}
[/sourcecode]

To install the plug-ins specified in your package.json type:

npm install

Gruntfile.js

Gruntfile.js consists of 3 sections:

  • Configuring predefined tasks
  • Load the predefined tasks (from Grunt plug-ins)
  • Add user-defined tasks

Below is an example of a Gruntfile.js:

[sourcecode language=”javascript”]
‘use strict’;

module.exports = function(grunt) {

// Configuring predefined tasks
grunt.initConfig({
pkg : grunt.file.readJSON(‘package.json’),

watch : {
options : {
livereload : true
},
sass : {
files : [‘sass/{,**/}*.{scss,sass}’],
tasks : [‘compass:dev’],
},
coffee : {
files : [‘coffeescript/**/*.coffee’],
tasks : [‘coffee:dev’]
}
},

compass : {
options : {
config : ‘config.rb’,
bundleExec : true
},
dev : {
options : {
environment : ‘development’,
force : true
}
},
dist : {
options : {
environment : ‘production’,
force : true
}
}
},

coffee : {
options : {
join : true
},
dev : {
options : {
sourceMap : true
},
files : {
‘js/my-theme-behaviors.js’ : [‘<%= pkg.coffeeScriptFile %>‘]
}
},
dist : {
options : {
sourceMap : false
},
files : {
‘js/my-theme-behaviors.normal.js’ : [‘coffeescript/my-theme-behaviors.coffee’]
}
}
},

uglify : {
dev : {
options : {
mangle : false,
compress : false,
beautify : true
},
files : [{
expand : true,
cwd : ‘js’,
src : [‘**/*.js’, ‘!**/*.min.js’],
dest : ‘js’,
ext : ‘.min.js’
}]
},
dist : {
options : {
mangle : true,
compress : true
},
files : [{
expand : true,
cwd : ‘js’,
src : [‘**/*.normal.js’, ‘!**/*.min.js’],
dest : ‘js’,
ext : ‘.js’
}]
}
}
});

// Load predefined tasks
grunt.loadNpmTasks(‘grunt-contrib-watch’);
grunt.loadNpmTasks(‘grunt-contrib-compass’);
grunt.loadNpmTasks(‘grunt-contrib-uglify’);
grunt.loadNpmTasks(‘grunt-contrib-coffee’);

// User-defined tasks
grunt.registerTask(‘build’, [‘coffee:dist’, ‘uglify:dist’, ‘compass:dist’]);
};
[/sourcecode]

Configuring Predefined Tasks

Line 6 is the start of the configuration of predefined tasks. package.json is imported so any properties defined there can be used in Gruntfile.js. For example in package.json I’ve defined a property called coffeeScriptFile and have used it on line 51, pkg.coffeeScriptFile. These template strings are surrounded by <%= %>.

Each task has a number of targets. For example compass on line 23 has targets dev and dist. You can run a task/target like this: compass:dev (line 15). If you don’t specify the target it will run all the targets. So for example when you type grunt watch, it will run each of the targets in that task. You could do grunt watch:sass if you just wanted to compile the Sass.

At the start of each task you can add an optional options section. This can then be overridden in the target. So in the above example the coffee task sets join to true for all targets (line 44) and the dev and dist targets set sourceMap to true (line 48) and false (line 56) respectively. See here for more on configuring tasks

Creating User-Defined Tasks

To define your own tasks you would use something like this:

grunt.registerTask('build', ['coffee:dist', 'uglify:dist', 'compass:dist']);

To run this task you would type:

grunt build

And it would run coffee:dist, uglify:dist and compass:dist. You can also define a default task:

grunt.registerTask('default', ['build'])

Which can be run from the command line like this:

grunt

For more creating user-defined tasks see here.

Plug-ins

You can find a list of Grunt plug-ins here. And install them like this:

npm install <plug-in> --save-dev

–save-dev adds the dependency to package.json.

These are the plug-ins I’ve found most useful:

Comments are closed