Creating tasks

任务是 Grunt 的核心。你最常做的事情,比如 jshintnodeunit。每次运行 Grunt 时,你都会指定一个或多个要运行的任务,这告诉 Grunt 你想让它做什么。

如果你没有指定任务,但定义了一个名为 "default" 的任务,那么这个任务将(毫不奇怪地)默认运行。

别名任务

如果指定了任务列表,新任务将成为一个或多个其他任务的别名。每当运行这个"别名任务"时,taskList 中指定的每个任务都将按指定顺序运行。taskList 参数必须是一个任务数组。

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

这个示例别名任务定义了一个 "default" 任务,如果执行 Grunt 时没有指定任何任务,将自动运行 "jshint"、"qunit"、"concat" 和 "uglify" 任务:

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

还可以指定任务参数。在这个示例中,别名 "dist" 运行 "concat" 和 "uglify" 任务,每个任务都带有 "dist" 参数:

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

多任务

当运行多任务时,Grunt 会在 Grunt 配置中查找同名属性。多任务可以有多个配置,使用任意命名的"目标"定义。

grunt concat:foogrunt concat:bar 这样同时指定任务和目标将只处理指定目标的配置,而运行 grunt concat 将遍历所有目标,依次处理每个目标。请注意,如果任务已使用 grunt.task.renameTask 重命名,Grunt 将在配置对象中查找任务名称的属性。

大多数贡献任务,包括 grunt-contrib-jshint 插件的 jshint 任务grunt-contrib-concat 插件的 concat 任务都是多任务。

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

给定指定的配置,这个示例多任务将在通过 grunt log:foo 运行 Grunt 时记录 foo: 1,2,3,或者在通过 grunt log:bar 运行时记录 bar: hello world。如果以 grunt log 运行 Grunt,它将依次记录 foo: 1,2,3bar: hello worldbaz: 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);
});

"基本"任务

当运行基本任务时,Grunt 不查看配置或环境——它只是运行指定的任务函数,将任何指定的以冒号分隔的参数作为函数参数传入。

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

这个示例任务在通过 grunt foo:testing:123 运行 Grunt 时记录 foo, testing 123。如果任务不带参数运行,如 grunt foo,则任务记录 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);
  }
});

自定义任务

你可以对任务进行疯狂的定制。如果你的任务不遵循"多任务"结构,请使用自定义任务。

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

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

grunt.registerTask('foo', 'My "foo" task.', function() {
  // 在 "foo" 完成后按顺序排队 "bar" 和 "baz" 任务。
  grunt.task.run('bar', 'baz');
  // 或者:
  grunt.task.run(['bar', 'baz']);
});

任务可以是异步的。

grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() {
  // 强制任务进入异步模式并获取 "done" 函数的句柄。
  var done = this.async();
  // 运行一些同步操作。
  grunt.log.writeln('Processing task...');
  // 以及一些异步操作。
  setTimeout(function() {
    grunt.log.writeln('All done!');
    done();
  }, 1000);
});

任务可以访问自己的名称和参数。

grunt.registerTask('foo', 'My "foo" task.', function(a, b) {
  grunt.log.writeln(this.name, a, b);
});

// 使用方式:
// grunt foo
//   记录:'foo',undefined,undefined
// grunt foo:bar
//   记录:'foo','bar',undefined
// grunt foo:bar:baz
//   记录:'foo','bar','baz'

如果记录了任何错误,任务可以失败。

grunt.registerTask('foo', 'My "foo" task.', function() {
  if (failureOfSomeKind) {
    grunt.log.error('This is an error message.');
  }

  // 如果此任务有错误,则通过返回 false 来失败
  if (ifErrors) { return false; }

  grunt.log.writeln('This is the success message');
});

当任务失败时,除非指定了 --force,否则所有后续任务都将中止。

grunt.registerTask('foo', 'My "foo" task.', function() {
  // 同步失败。
  return false;
});

grunt.registerTask('bar', 'My "bar" task.', function() {
  var done = this.async();
  setTimeout(function() {
    // 异步失败。
    done(false);
  }, 1000);
});

任务可以依赖于其他任务的成功执行。请注意,grunt.task.requires 不会实际运行其他任务。它只是检查该任务是否已运行且未失败。

grunt.registerTask('foo', 'My "foo" task.', function() {
  return false;
});

grunt.registerTask('bar', 'My "bar" task.', function() {
  // 如果 "foo" 任务失败或从未运行,则使任务失败。
  grunt.task.requires('foo');
  // 如果 "foo" 任务成功运行,则执行此代码。
  grunt.log.writeln('Hello, world.');
});

// 使用方式:
// grunt foo bar
//   不记录,因为 foo 失败。
//   ***注意:这是空格分隔的顺序命令的示例,
//   (类似于执行两行代码:`grunt foo` 然后 `grunt bar`)
// grunt bar
//   不记录,因为 foo 从未运行。

如果所需的配置属性不存在,任务可以失败。

grunt.registerTask('foo', 'My "foo" task.', function() {
  // 如果缺少 "meta.name" 配置属性,则使任务失败
  // 格式 1:字符串
  grunt.config.requires('meta.name');
  // 或格式 2:数组
  grunt.config.requires(['meta', 'name']);
  // 有条件地记录...
  grunt.log.writeln('只有在配置中定义了 meta.name 时才会记录。');
});

任务可以访问配置属性。

grunt.registerTask('foo', 'My "foo" task.', function() {
  // 记录属性值。如果属性未定义,则返回 null。
  grunt.log.writeln('meta.name 属性是:' + grunt.config('meta.name'));
  // 也记录属性值。如果属性未定义,则返回 null。
  grunt.log.writeln('meta.name 属性是:' + grunt.config(['meta', 'name']));
});

查看 贡献任务 以获取更多示例。

CLI 选项 / 环境

使用 process.env 访问环境变量

使用 CLI 页面上阅读更多关于可用命令行选项的信息。

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

很可能发生这种情况是因为你忘记调用 this.async 方法来告诉 Grunt 你的任务是异步的。为了简单起见,Grunt 使用同步编码风格,可以通过在任务体内调用 this.async() 切换到异步。

请注意,向 done() 函数传递 false 告诉 Grunt 任务已失败。

例如:

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

额外参考

如果你需要额外的参考来创建任务,请查看 API 文档。