• 创建任务
    • 别名任务
    • 多任务
    • ‘基本’任务
    • 自定义任务
    • CLI选项和环境
    • 为什么我的异步任务没有完成?

    创建任务

    任务是Grunt的基本组成。例如你常用的工具:jshintnodeunit。当你每次运行Grunt时,你可以指定它(Grunt)运行一个或者多个任务,通过这些任务来告诉Grunt你想要它做什么事情。

    如果你没有指定任务,但是定义了一个名为”default”的任务,那么该任务(default任务)将默认运行(不要惊讶,顾名思义它代表默认会运行哪些定义好的任务)。

    别名任务

    如果指定了一个任务列表,新任务(名)便是其他一个或多个任务的别名。每当运行’别名任务’时,指定在taskList中的每个任务(指在grunt.initConfig()中定义的任务)都会按照指定它们的顺序运行。taskList参数必须是一个任务数组。其语法如下:

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

    这里有一个例子,它定义了一个名为’default’别名任务,如果运行Grunt时没有指定任何任务,它将自动运行’jshint’,’qunit’,’concat’和’uglify’任务。

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

    可以给任务指定参数。在下面的例子中,别名任务’dist’会运行’concat’和’uglify’这两个任务,并且每个任务都带有一个’dist’参数:

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

    多任务

    当运行一个多任务时,Grunt会自动从项目的配置对象中查找同名属性。多任务可以有多个配置,并且可以使用任意命名的’targets’。

    同时指定像grunt concat:foo或者grunt concat:bar这样的任务和目标,在运行时Grunt只会处理指定目标的配置;然而如果运行grunt concat,将会遍历所有的目标, 并按任务指定的顺序处理每个目标。注意,如果一个任务已经使用grunt.renameTask重命名过,Grunt将会自动在配置对象中查找新任务名称属性。

    大部分的contrib任务(主要是指官方提供的任务),包括grunt-contrib-jshint插件的jshint任务,以及grunt-contrib-concat插件的concat任务都是多任务形式的。

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

    鉴于指定的配置,这里有一个示例演示了如果通过grunt log:foo运行Grunt,它会输出foo: 1,2,3;如果通过grunt log:bar来运行Grunt, 它会输出bar: hello world。然而如果通过grunt log运行Grunt, 它会输出foo: 1,2,3,然后是bar: hello world,最后是baz: false(任务目标会按照指定的顺序进行处理)。

    1. grunt.initConfig({
    2. log: {
    3. foo: [1,2,3],
    4. bar: 'hello world',
    5. baz: false
    6. }
    7. });
    8. grunt.registerTask('log','log stuff.', function(){
    9. grunt.log.writeln(this.target + ': ' + this.data);
    10. });

    ‘基本’任务

    当运行一个基本任务时,Grunt并不会查找配置和检查运行环境—它仅仅运行指定的任务函数,可以传递任意使用冒号分割的参数作为任务函数的参数(注意多任务中的冒号并不是传递参数,而是指定具体任务的目标)。

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

    这里有一个例子演示了如果通过grunt foo:testing:123运行Grunt将输出foo, testing 123。如果运行这个任务时不传递参数,只运行grunt foo,那么这个任务会输出foo, no args

    1. grunt.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) {
    2. if (arguments.length === 0) {
    3. grunt.log.writeln(this.name + ", no args");
    4. } else {
    5. grunt.log.writeln(this.name + ", " + arg1 + " " + arg2);
    6. }
    7. });

    自定义任务

    你可能会着迷于任务。但是如果你的任务并没有遵循多任务结构,那么你可以使用自定义任务。

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

    在任务的内部,你还可以运行其他的任务。

    1. grunt.registerTask('foo', 'My "foo" task.', function() {
    2. //在foo任务完成之后一次运行队列中的bar和baz任务
    3. grunt.task.run('bar', 'baz');
    4. // Or:
    5. grunt.task.run(['bar', 'baz']);
    6. });

    任务还可以是异步的.

    1. grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() {
    2. //将任务转变为异步模式并交给done函数处理
    3. var done = this.async();
    4. //同步任务
    5. grunt.log.writeln('Processing task...');
    6. //异步任务
    7. setTimeout(function() {
    8. grunt.log.writeln('All done!');
    9. done();
    10. }, 1000);
    11. });

    任务也可以访问它们自身名称和参数.

    1. grunt.registerTask('foo', 'My "foo" task.', function(a, b) {
    2. grunt.log.writeln(this.name, a, b);
    3. });
    4. // 用法:
    5. // grunt foo foo:bar
    6. // logs: "foo", undefined, undefined
    7. // logs: "foo", "bar", undefined
    8. // grunt foo:bar:baz
    9. // logs: "foo", "bar", "baz"

    如果任务记录到错误信息,还可以终止任务执行(通过标记任务失败的方式)。

    1. grunt.registerTask('foo', 'My "foo" task.', function() {
    2. if (failureOfSomeKind) {
    3. grunt.log.error('This is an error message.');
    4. }
    5. //如果这个任务抛出错误则返回false
    6. if (ifErrors) { return false; }
    7. grunt.log.writeln('This is the success message');
    8. });

    当任务失败时,所有后续的除了指定--force标志的任务都会终止。

    1. grunt.registerTask('foo', 'My "foo" task.', function() {
    2. // Fail synchronously.
    3. return false;
    4. });
    5. grunt.registerTask('bar', 'My "bar" task.', function() {
    6. var done = this.async();
    7. setTimeout(function() {
    8. // Fail asynchronously
    9. done(false);
    10. }, 1000);
    11. });

    任务还可以依赖于其他任务的成功执行。注意grunt.task.requires并不会运行其他任务(比如参数中指定的任务)。它仅仅检查那些任务(其他任务)的运行并没有失败(即其他任务,也就是所依赖的任务是否失败)。

    1. grunt.registerTask('foo', 'My "foo" task.', function() {
    2. return false;
    3. });
    4. grunt.registerTask('bar', 'My "bar" task.', function() {
    5. //如果foo任务运行失败或者没有运行则任务失败
    6. grunt.task.requires('foo');
    7. //如果foo任务运行成功则执行这里的代码
    8. grunt.log.writeln('Hello, world.');
    9. });
    10. // 用法
    11. // grunt foo bar
    12. // 没有输出,因为foo失败
    13. // grunt bar
    14. // 没有输出,因为foo从未运行

    如果任务需要的配置属性不存在,任务也可能失败。

    1. grunt.registerTask('foo', 'My "foo" task', function(){
    2. //如果缺省"meta.name"配置属性则任务失败
    3. grunt.config.requires('meta.name');
    4. //与上一句相同,如果缺省"meta.name"配置属性则任务失败
    5. grunt.config.requires(['meta', 'name']);
    6. //附加记录
    7. grunt.log.writeln('This will only log if meta.name is defined in the config');
    8. });

    任务还可以访问配置属性。

    1. grunt.registerTask('foo', 'My "foo" task.', function(){
    2. // 记录属性值,如果属性未定义则返回null
    3. grunt.log.writeln('The meta.name property is:' + grunt.config('meta.name'));
    4. // 同样的记录属性值,如果属性未定义则返回null
    5. grunt.log.writeln('The meta.name property is:' + grunt.config(['meta', 'name']));
    6. });

    在contrib tasks中可以查看更多的例子。

    CLI选项和环境

    TODO(从FAQ拉取,推荐process.env)

    为什么我的异步任务没有完成?

    可能由于你忘记调用this.async方法来告诉Grunt你的任务是异步的,那么就可能会发生这种情况(异步任务失败)。为了简单起见,Grunt使用同步的编码风格,可以在任务体中通过调用this.async将该任务(调用这个方法的任务)转换为异步的。

    注意传递falsedone函数就会告诉Grunt任务已经失败。

    例如:

    1. grunt.registerTask('asyncme', 'My asynchronous task.', function(){
    2. var done = this.async();
    3. doSomethingAsync(done);
    4. });