In this chapter, let us learn about creating tasks. Whenever you run Grunt, one or more tasks are specified to run that notifies Grunt what you would like it to do. If you specify the default task, then it will run by default.
Whenever a list of tasks is specified, one or more other tasks can be aliased by a new task. Running the alias will in turn run every specified tasks in the taskList. The taskList argument should be an array of tasks as shown below −
grunt.registerTask(taskName, [description, ] taskList)
For instance, when you define a taskList with jshint, concat, and uglify tasks and specify the taskName as default, all the listed tasks will be run automatically if Grunt is executed without specifying any tasks.
grunt.registerTask('default', ['jshint', 'concat', 'uglify']);
You can also specify task arguments as shown below −
grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);
In the above task, the alias dist runs both the concat and uglify tasks.
Whenever you run multiple tasks, Grunt searches for a property of the same name in the Grunt configuration. These tasks can have multiple configurations, which will be defined using arbitrarily named targets.
When you specify both a task and target, only the specified target configuration will be processed.
grunt concat:foo
The above command will run only the target foo.
When you specify only a task, then all the targets will be processed.
grunt concat
The above command will iterate over all the targets of concat task.
When you rename a task with grunt.task.renameTask, a property with new task name is searched in the config object by Grunt.
grunt.initConfig({ log: { foo: [1, 2, 3], bar: 'Welcome to howcodex', sap: true } }); grunt.registerMultiTask('log', 'Log stuff.', function() { grunt.log.writeln(this.target + ': ' + this.data); });
In the above example, multi task will log foo: 1,2,3 if Grunt was run through grunt log:foo or it will log bar: Welcome to howcodex whenever run through grunt log:bar. It will log foo: 1,2,3 then bar: Welcome to howcodex then sap: true when Grunt runs as grunt log.
Whenever you run a basic task, Grunt will not search the configuration or environment. Instead it runs the task function which is specified, passes any colon-separated arguments specified in as function arguments.
grunt.registerTask(taskName, [description, ] taskFunction)
In the following example, the task logs foo, testing 123 if Grunt is executed through grunt foo:testing:123 command. Whenever the task is run without arguments as grunt foo, the task will log foo, no args.
grunt.registerTask('foo', 'A simple task to logs stuff.', function(arg1, arg2) { if (arguments.length === 0) { grunt.log.writeln(this.name + ", no args"); } else { grunt.log.writeln(this.name + ", " + arg1 + " " + arg2); } });
If you do not want to follow multi task structure, you can define your custom task as shown below −
grunt.registerTask('default', 'My "default" task description.', function() { grunt.log.writeln('Currently running the "default" task.'); });
It is possible to run a task within another task as shown below −
grunt.registerTask('foo', 'My "foo" task.', function() { // Enqueue bar and baz tasks, to run after foo completes, in-order. grunt.task.run('bar', 'baz'); // Or: grunt.task.run(['bar', 'baz']); });
You can also create asynchronous tasks as shown below −
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 your task..'); // Run some async stuff. setTimeout(function() { grunt.log.writeln('Finished!'); done(); }, 1000); });
You can create tasks which can access their name and arguments as shown below −
grunt.registerTask('foo', 'My task "foo" .', function(a, b) { grunt.log.writeln(this.name, a, b); }); // Usage: // grunt foo // logs: "foo", undefined, undefined // grunt foo:bar // logs: "foo", "bar", undefined // grunt foo:bar:baz // logs: "foo", "bar", "baz"
You can create your task in such a way that, whenever any errors are logged, the tasks can fail as shown below −
grunt.registerTask('foo', 'My task "foo" .', function() { if (failureOfSomeKind) { grunt.log.error('This is an error message.'); } // If this task had errors then fail by returning false if (ifErrors) { return false; } grunt.log.writeln('This is success message'); });
Whenever a task fails, every following task will be terminated unless --force was specified.
grunt.registerTask('foo', 'My task "foo" .', function() { // Fail synchronously. return false; }); grunt.registerTask('bar', 'My task "bar" .', function() { var done = this.async(); setTimeout(function() { // Fail asynchronously. done(false); }, 1000); });
Tasks can be dependent on other tasks for successful execution. Remember that the grunt.task.requires will not actually execute other task(s), instead it will only check to see whether it has executed and not failed.
grunt.registerTask('foo', 'My task "foo" .', function() { return false; }); grunt.registerTask('bar', 'My task "bar" .', function() { // Fail task if foo task failed or never ran. grunt.task.requires('foo'); // This code executes if the foo task executed successfully. grunt.log.writeln('Hello, World.. Welcome to Howcodex!..'); }); // Usage: // grunt foo bar doesn't log, because foo failed to execute. // **Note: This is an example of space-separated sequential commands, // (similar to executing two lines of code: `grunt foo` then `grunt bar`) // grunt bar doesn't log, because foo never ran.
Tasks can even fail whenever required configuration properties are not found.
grunt.registerTask('foo', 'My task "foo" .', function() { // Fail task if meta.name config properties is missing // Format 1: String grunt.config.requires('meta.name'); // or Format 2: Array grunt.config.requires(['meta', 'name']); // Log... conditionally. grunt.log.writeln('This only log if meta.name is defined in the config.'); });
Tasks can access the configuration properties as shown below −
grunt.registerTask('foo', 'My task "foo" .', function() { // Log the value of the property. Returns null if the property is undefined. grunt.log.writeln('The meta.name property is: ' + grunt.config('meta.name')); // Also logs the value of the property. Returns null if the property is undefined. grunt.log.writeln('The meta.name property is: ' + grunt.config(['meta', 'name'])); });