Creating Tasks - Ramanonos/grunt GitHub Wiki
Tasks are grunt's bread and butter. The stuff you do most often, like jshint
or nodeunit
. Every time Grunt is run, you specify one or more tasks to run, which tells Grunt what you'd like it to do.
If you don't specify a task, but a task named "default" has been defined, that task will run (unsurprisingly) by default.
If a task list is specified, the new task will be an alias for one or more other tasks. Whenever this "alias task" is run, every specified tasks in taskList
will be run, in the order specified. The taskList
argument must be an array of tasks.
grunt.registerTask(taskName, [description, ] taskList)
This example alias task defines a "default" task whereby the "jshint", "qunit", "concat" and "uglify" tasks are run automatically if Grunt is executed without specifying any tasks:
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
Task arguments can be specified as well. In this example, the alias "dist" runs both the "concat" and "min" tasks, each with a "dist" argument:
grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);
When a multi task is run, Grunt looks for a property of the same name in the Grunt configuration. Multi-tasks can have multiple configurations, defined using arbitrarily named "targets."
Specifying both a task and target like grunt concat:foo
or grunt concat:bar
will process just the specified target's configuration, while running grunt concat
will iterate over all targets, processing each in turn. Note that if a task has been renamed with grunt.renameTask, Grunt will look for a property with the new task name in the config object.
Most of the contrib tasks, including the grunt-contrib-jshint plugin jshint task, concat task and grunt-contrib-concat plugin concat task are multi tasks.
grunt.registerMultiTask(taskName, [description, ] taskFunction)
Given the specified configuration, this example multi task would log foo: 1,2,3
if Grunt was run via grunt log:foo
, or it would log bar: hello world
if Grunt was run via grunt log:bar
. If Grunt was run as grunt log
however, it would log foo: 1,2,3
then bar: hello world
then baz: false
.
grunt.initConfig({
log: {
foo: [1, 2, 3],
bar: 'hello world',
baz: false
}
});
grunt.registerMultiTask('log', 'Log stuff.', function() {
grunt.log.writeln(this.target + ': ' + this.data);
});
When a basic task is run, Grunt doesn't look at the configuration or environment—it just runs the specified task function, passing any specified colon-separated arguments in as function arguments.
grunt.registerTask(taskName, [description, ] taskFunction)
This example task logs foo, testing 123
if Grunt is run via grunt foo:testing:123
. If the task is run without arguments as grunt foo
the task logs foo, no args
.
grunt.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) {
if (arguments.length === 0) {
grunt.log.writeln(this.name + ", no args");
} else {
grunt.log.writeln(this.name + ", " + arg1 + " " + arg2);
}
});
You can go crazy with tasks. If your tasks don't follow the "multi task" structure, use a custom task.
grunt.registerTask('default', 'My "default" task description.', function() {
grunt.log.writeln('Currently running the "default" task.');
});
Inside a task, you can run other tasks.
grunt.registerTask('foo', 'My "foo" task.', function() {
// Enqueue "bar" and "baz" tasks, to run after "foo" finishes, in-order.
grunt.task.run('bar', 'baz');
// Or:
grunt.task.run(['bar', 'baz']);
});
Tasks can be asynchronous.
grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() {
// Force task into async mode and grab a handle to the "done" function.
var done = this.async();
// Run some sync stuff.
grunt.log.writeln('Processing task...');
// And some async stuff.
setTimeout(function() {
grunt.log.writeln('All done!');
done();
}, 1000);
});
Tasks can access their own name and arguments.
grunt.registerTask('foo', 'My "foo" task.', function(a, b) {
grunt.log.writeln(this.name, a, b);
});
// Usage:
// grunt foo foo:bar
// logs: "foo", undefined, undefined
// logs: "foo", "bar", undefined
// grunt foo:bar:baz
// logs: "foo", "bar", "baz"
Tasks can fail if any errors were logged.
grunt.registerTask('foo', 'My "foo" task.', function() {
if (failureOfSomeKind) {
grunt.log.error('This is an error message.');
}
// Fail by returning false if this task had errors
if (ifErrors) { return false; }
grunt.log.writeln('This is the success message');
});
When tasks fail, all subsequent tasks will be aborted unless --force
was specified.
grunt.registerTask('foo', 'My "foo" task.', function() {
// Fail synchronously.
return false;
});
grunt.registerTask('bar', 'My "bar" task.', function() {
var done = this.async();
setTimeout(function() {
// Fail asynchronously.
done(false);
}, 1000);
});
Tasks can be dependent on the successful execution of other tasks. Note that grunt.task.requires
won't actually RUN the other task(s). It'll just check to see that it has run and not failed.
grunt.registerTask('foo', 'My "foo" task.', function() {
return false;
});
grunt.registerTask('bar', 'My "bar" task.', function() {
// Fail task if "foo" task failed or never ran.
grunt.task.requires('foo');
// This code executes if the "foo" task ran successfully.
grunt.log.writeln('Hello, world.');
});
// Usage:
// grunt foo bar
// doesn't log, because foo failed.
// grunt bar
// doesn't log, because foo never ran.
Tasks can fail if required configuration properties don't exist.
grunt.registerTask('foo', 'My "foo" task.', function() {
// Fail task if "meta.name" config prop is missing.
grunt.config.requires('meta.name');
// Also fails if "meta.name" config prop is missing.
grunt.config.requires(['meta', 'name']);
// Log... conditionally.
grunt.log.writeln('This will only log if meta.name is defined in the config.');
});
Tasks can access configuration properties.
grunt.registerTask('foo', 'My "foo" task.', function() {
// Log the property value. Returns null if the property is undefined.
grunt.log.writeln('The meta.name property is: ' + grunt.config('meta.name'));
// Also logs the property value. Returns null if the property is undefined.
grunt.log.writeln('The meta.name property is: ' + grunt.config(['meta', 'name']));
});
Take a look at the contrib tasks for more examples.
TODO (pull from FAQ, recommend process.env)
Chances are this is happening because you have forgotten to call the this.async method to tell Grunt that your task is asynchronous. For simplicity's sake, Grunt uses a synchronous coding style, which can be switched to asynchronous by calling this.async()
within the task body.
Note that passing false
to the done()
function tells Grunt that the task has failed.
For example:
grunt.registerTask('asyncme', 'My asynchronous task.', function() {
var done = this.async();
doSomethingAsync(done);
});