How to Grunt
Introduction
I had the pleasure of attending the second day of jQueryTO this past weekend and had a great time.
It was pretty awesome to see the presentations given by people like Paul Irish, Tim Branyen and Derick Bailey. I've read a lot about the things they've done to try and advance the web and educate people, so it was pretty cool to see and hear them live. I saw Addy Osmani in the crowd, although I missed his keynote on the first day.
One presentation that got me itching to get back to my terminal window was Dan Heberden's presentation on Grunt.
Why Grunt?
Using Makefiles, Rakefiles, bash scripts and running commands can get quite cumbersome after a while. You have to be aware of where you run some commands, you might have to install some gems, you might have to run a command after editing certain types of files...the list goes on.
Grunt is a task runner. It was created by Ben Alman to deal with these issues, specifically.
They also have a ton of supported plugins that make it easy to get started.
Getting started
The Grunt website has some detailed instructions to help you get started but they can be summed up in a few simple steps.
You can also clone my repo containing all of the files in this post:
git clone https://github.com/donaldducky/grunt-example
1. Install Grunt
# This installs grunt 0.4 at the time of this writing
npm uninstall grunt # skip this step if you have never installed grunt
npm install -g grunt-cli
2. Setup your project's package.json
This is the minimal package.json
you can create.
{
"name": "grunt-example",
"version": "0.1.0"
}
3. Require Grunt
npm install grunt --save-dev
4. Create Gruntfile
// Gruntfile.js
module.exports = function(grunt) {
// Configure
grunt.initConfig({
});
};
This is a barebones Gruntfile. We'll add to it in the next part.
Tasks
At this point, you can create tasks for your project.
For example, I like to use less as my CSS preprocessor.
1. Install grunt-contrib-less
npm install grunt-contrib-less --save-dev
2. Create a less task
module.exports = function(grunt) {
// Configure
grunt.initConfig({
// The less task.
less: {
// This is the target's name "production".
// You can run this task like this:
// grunt less:production
production: {
options: {
// Set the option to compress the resulting css.
yuicompress: true
},
files: {
// Create a file called "public/css/site.css" from "less/site.less".
// Note: If the directory public/css does not exist, it will be
// created by the task.
"public/css/site.css": "less/site.less"
}
}
}
});
// Load tasks
grunt.loadNpmTasks('grunt-contrib-less');
};
Now, running the task will compile the less files.
$ grunt less
Running "less:production" (less) task
File public/css/site.css created.
Done, without errors.
The 'default' task
If you're like me, typing grunt less:production
or grunt less
is too much work.
Luckily, Grunt has the concept of a default task.
module.exports = function(grunt) {
...
// Default task.
// These are the tasks that get run when you run Grunt without any arguments.
// To add more tasks, just add them to the array.
grunt.registerTask('default', [ 'less' ]);
};
Now, I can compile my less files like so:
$ grunt
Running "less:production" (less) task
File public/css/site.css created.
Done, without errors.
Typing 'grunt' takes forever!
I agree! Anything we can do to eliminate a step and make us lazier is usually better.
npm install grunt-contrib-watch --save-dev
Add a new task to the initConfig
block and load the watch task.
module.exports = function(grunt) {
// Configure
grunt.initConfig({
...
// Watch task.
watch: {
// Keep an eye on those stylesheets.
styles: {
// The path 'less/**/*.less' will expand to match every less file in
// the less directory.
files: [ 'less/**/*.less' ],
// The tasks to run
tasks: [ 'less' ]
}
}
...
});
// Load tasks
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
...
};
Run the watch command:
$ grunt watch
Running "watch" task
Waiting...
Edit your less files and watch magic happen!
$ grunt watch
Running "watch" task
Waiting...OK
>> File "less/site.less" changed.
Running "less:production" (less) task
File public/css/site.css created.
Done, without errors.
Completed in 0.625s at Fri Mar 08 2013 19:24:19 GMT-0500 (EST) - Waiting...
Grunt is awesome!
I feel like now's a good time to stop. There is definitely a lot more to Grunt but this post is long already.
Thank you Ben Alman and the rest of the Grunt community for providing this tool and all of the plugins!
Have fun making Grunt do all the boring stuff for you!
A few links to learn more about Grunt
- Grunt - the Grunt homepage
- Grunt Plugins - the Grunt plugin repository
- grunt-contrib-livereload - because who likes to refresh pages?
Some things I want to look into
- grunt-init - for project scaffolding
- Bower - Twitter's "package manager for the web"
- Yeoman - to see how it's progressing and find out how it's using Grunt and Bower