So, what's this Grunt? Basically, it's a Javascript based task runner, which can be used for a huge range of, well, tasks!
In my use case Grunt performs a few tasks:
First, a very quick walkthrough on how to get Grunt up and running on an Ubuntu system.
This isn't so much a tutorial, but more a walk through of my setup, for a proper introduction check out [http://gruntjs.com/getting-started] and [http://www.sitepoint.com/writing-awesome-build-script-grunt/]
First, install NodeJS:
sudo apt-get install nodejs nodejs-dev npmThen, install GruntJS:
sudo npm install -g grunt-cliAt this point, you have Grunt, but to use it you need to add it, and modules to your project, so, in your project directory:
npm install grunt --save-devThe next step is to find the plugins for the tasks you need, here: [http://gruntjs.com/plugins]
So, to add the required modules, you can either add them to your package.json
file, and run npm install, and it will fetch and install your packages, or
you can run commands like:
npm install grunt-contrib-watch --save-devThis will install the module, and save the dependency to your package.json
file, which is used to made Node.js modules.
This is my package.json
{
"engines": {
"node": ">= 0.10.0"
},
"devDependencies": {
"grunt": "~0.4.5",
"grunt-bower-task": "~0.4.0",
"grunt-composer": "^0.4.4",
"grunt-concat-css": "~0.3.1",
"grunt-contrib-concat": "~0.4.0",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-less": "~0.11.3",
"grunt-contrib-nodeunit": "~0.4.1",
"grunt-contrib-uglify": "~0.5.0",
"grunt-contrib-watch": "~0.6.1",
"grunt-githooks": "~0.3.1",
"grunt-parallel-behat": "^0.3.6",
"grunt-phpunit": "~0.3.3",
"grunt-shell": "^1.1.1"
},
"scripts": {
"postinstall": "grunt githooks"
}
}To use it, just create the package.json file, and run npm install, and
all of the listed modules will be installed!
Grunt takes its own configuration from Gruntfile.js, which I'll go through
in blocks, starting here, at the top, I've skipped over a few bits, but my full Gruntfile.js is here:
At the start, we load our tasks using grunt.loadNpmTasks():
/*global module:false*/
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-composer');
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-concat-css');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-bower-task');
grunt.loadNpmTasks('grunt-githooks');
grunt.loadNpmTasks('grunt-parallel-behat');Then we begin our configuration using grunt.initConfig(), which is passed an
object containing our configuration:
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON('package.json'),
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>
' +
'<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */
',Next comes the configuration for our individual modules, here are a few examples:
// Task configuration.
less: {
development: {
options: {
compress: false, // we don't minify the result, we do this later.
},
files: {
//"../app/assets/stylesheets/styles.css": "../app/assets/less/styles.less",
"../app/assets/stylesheets/bootstrap.css": "../app/assets/less/bootstrap.less",
}
}
},
concat_css: {
options: {
// Task-specific options go here.
},
styles: {
src: [
'../app/assets/stylesheets/bootstrap.css',
'./assets/jquery-ui/themes/smoothness/jquery-ui.css'
],
dest: '../public/assets/stylesheets/styles.css'
}
},
The 'watch' task is perhaps the most useful, and interesting, as it can be used while developing to monitor changes in specified files, and trigger a task when changes are detected:
watch: {
js_frontend: {
files: [
//watched files
'./lib/jquery/dist/jquery.js',
'./lib/jquery-ui/jquery-ui.js',
'./lib/matchHeight/jquery.matchHeight-min.js',
'./lib/bootstrap/dist/js/bootstrap.js',
'../assets/js/scripts.js'
],
tasks: ['concat', 'uglify'], //tasks to run
options: {
livereload: true //reloads the browser
}
},
styles: {
files: ['./lib/bootstrap/less/*.less',
'../assets/less/*.less'
], //watched files
tasks: ['less', 'concat_css'], //tasks to run
options: {
livereload: true //reloads the browser
}
},
fonts: {
files: ['./lib/bootstrap/fonts/*'],
tasks: ['copy'],
options: {
livereload: true
}
}
}
});
Next come the tasks which bind together other tasks:
// Default task.
grunt.registerTask('default', ['concat', 'uglify', 'less', 'concat_css', 'copy']);
grunt.registerTask('pre-commit', ['composer:install', 'behat', 'phpspec']);
grunt.registerTask('merge', ['concat', 'uglify', 'less', 'concat_css', 'copy', 'behat']);
grunt.registerTask('build', ['bower:install', 'concat', 'uglify', 'less', 'concat_css', 'copy']);
};
Anyway, that's it for now, I'll probably update this at some point, so feel free
to check back.