Grunt Tasks

前言

  1. 翻译 http://gruntjs.com/creating-tasks 中的内容,并添加自己的理解
  2. 扩充内容,补充一些其他重要的内容,比如 task concurrent

注册任务 (Alias Tasks)

官方文档中,将这节命名为 Alias Tasks,感觉文不达意,所以将其更名为 Register Tasks
标准格式

1
$ grunt.registerTask(taskName, [description, ] taskList)

注册default task

1
$ grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);

当执行grunt命令的时候,无需指定任何参数,jshintqunitconcatuglify将会任务将会自动执行

注册指定名称的任务,这里注册为dist,然后使用grunt dist命令执行。

1
$ grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);

要注意的是,'concat:dist''uglify:dist'中的dist指的是任务参数

多任务 (Multi Tasks)

从标题上来看,多任务会产生误导,其实是指的含有多个子任务(Target)的任务。
注册的标准格式写法,

1
$ grunt.registerMultiTask(taskName, [description, ] taskFunction)

什么是多任务?

1
2
3
4
5
6
grunt.initConfig({
concat: {
foo: [1, 2, 3],
bar: 'hello world'
}
});

注:concatTaskfoobarTarget
这里其实表示的是concat Task 由两个 Targetfoobar,构成,而这里的 Target 才是最终执行的任务。
看看官方文档对多任务特性的描述,
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.
其实就一句话,concat其实就是一个包含多子任务(Target)Task,包含foobar两个“子任务”(在官方定义里面,称作”Target“,其实叫做子任务更好理解)。

下面给一个比较详细的例子来解释什么是 Multi Task

1
2
3
4
5
6
7
8
9
10
11
12
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);
});

执行任务

  1. 执行grunt log:foo,将打印foo: 1,2,3
    logTaskfoo子任务 Target
  2. 执行grunt log:bar,将打印bar: hello world
  3. 执行grunt log,将打印foo: 1,2,3thenbar: hello worldthenbaz: false

Task 的基本用法、参数

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.

1
grunt.registerTask(taskName, [description, ] taskFunction)

看如下的用例

1
2
3
4
5
6
7
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);
}
});

  1. 如果执行grunt foo:testing:123将打印foo, testing 123
    注意testing:123部分分别表示function(arg1, arg2)中的两个参数
  2. 如果执行grunt foo将打印foo, no args

自定义方法

You can go crazy with tasks. If your tasks don’t follow the “multi task” structure, use a custom task. 如果你的任务不是按照”multi task”的风格来定义的,使用自定义 Task。

定义 default

1
2
3
grunt.registerTask('default', 'My "default" task description.', function() {
grunt.log.writeln('Currently running the "default" task.');
});

Inside a task,you can run other tasks

1
2
3
4
5
6
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.

1
2
3
4
5
6
7
8
9
10
11
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);
});
task 可以异步执行;

Tasks can access their own name and arguments.

1
2
3
4
5
6
7
8
9
10
11
grunt.registerTask('foo', 'My "foo" task.', 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"

Fail I - if any errors were logged

Tasks can fail if any errors were logged.

1
2
3
4
5
6
7
8
9
10
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');
});

return false表示当前任务执行失败

Fail II - if required conf properties don’t exist

Tasks can fail if required configuration properties don’t exist.

1
2
3
4
5
6
7
8
9
grunt.registerTask('foo', 'My "foo" task.', function() {
// Fail task if "meta.name" config prop 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 will only log if meta.name is defined in the config.');
});

see grunt.config

–force

When tasks fail, all subsequent tasks will be aborted unless --force was specified. 当某一个任务失败,后续任务都会失败;除非在执行grunt命令的时候指定--force

1
2
3
4
5
6
7
8
9
10
11
12
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);
});

access conf properties

Tasks can access configuration properties.

1
2
3
4
5
6
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']));
});

dependent

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.
// ***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.

注意,是通过grunt.task.requires('foo');的方式进行依赖关系

Grunt concurrent tasks

refer to Grunt-concurrent