每當運行Grunt時, 你可以為其指定一個或多個任務, 這些任務用於告訴Grunt你想要它做什么事情。
如果你沒有指定一個任務,並且你已經定義一個名為 "default" 的任務,那么該任務將會默認被執行。
任務別名
如果指定了一個任務列表taskList,新任務名taskName將是這一個或多個指定任務的別名。當運行此 "任務別名" 時,在taskList
中指定的每個任務都會按照其出現的順序依次執行。taskList
參數必須是一個任務數組。grunt.registerTask(taskName, taskList)
舉個例子:
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
上面的任務別名案例中定義了一個 'default' 任務,如果運行Grunt時沒有指定任何任務,它將自動執行'jshint'、'qunit'、'concat' 和 'uglify' 任務。
還可以給任務指定參數。在下面的例子中,別名 "dist" 將執行 "concat" 和 "uglify" 兩個任務,並且它們都帶有一個 "dist" 參數:
grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);
多任務
當運行一個多任務時,Grunt會自動從項目的配置對象中查找同名屬性。多任務可以有多個配置,並且可以使用任意命名的'targets'。舉個例子:
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 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(任務目標會按照指定的順序進行處理)。
"基本" 任務
當一個基本任務執行時,Grunt並不會檢查配置和環境 -- 它僅僅執行指定的任務函數,並傳遞任何使用冒號分割的參數作為函數的參數。舉個例子:
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 foo:testing:123
,將輸出日志 foo, testing 123
。 如果執行這個任務時不傳遞參數,只是執行 grunt foo
,那么將輸出日志 foo, no args
。
自定義任務
如果你的任務沒有遵循 "多任務" 結構,那就可以使用自定義任務。比如:
grunt.registerTask('default', 'My "default" task description.', function() { grunt.log.writeln('Currently running the "default" task.'); });
任務的其他特性
在一個任務內部,你可以執行其他的任務。比如:
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']); });
任務也可以是異步的。比如:
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); });
任務也可以訪問它們自身名稱和參數。比如:
grunt.registerTask('foo', 'My "foo" task.', function(a, b) { grunt.log.writeln(this.name, a, b); }); // 用法: // grunt foo // logs: "foo", undefined, undefined // grunt foo:bar // logs: "foo", "bar", undefined // grunt foo:bar:baz // logs: "foo", "bar", "baz"
如果任務在執行時記錄到任何錯誤,那么任務就會失敗。當任務失敗時,所有的后續任務都將終止。比如:
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 // 沒有輸出,bar任務沒有運行,因為"foo"失敗,所以它后面的任務都將終止運行。 // grunt bar // 沒有輸出,bar任務運行,但運動到一半就停止了,因為"foo"從未運行,所以foo任務失敗,失敗后,bar任務也就停止了,因此沒有輸出。
注意 grunt.task.requires 並不會真正的運行其他任務,它僅僅檢查其它任務是否已經執行,並且沒有失敗。
任務還可以訪問配置屬性。比如:
grunt.registerTask('foo', 'My "foo" task.', function() { // 記錄屬性值,如果屬性未定義(undefined)則返回null。 grunt.log.writeln('The meta.name property is: ' + grunt.config('meta.name')); // 同樣的記錄屬性值,如果屬性未定義(undefined)則返回null。 grunt.log.writeln('The meta.name property is: ' + grunt.config(['meta', 'name'])); });
如果任務需要的配置屬性不存在,其也會失敗。比如:
grunt.registerTask('foo', 'My "foo" task.', function() { // 如果缺少"meta.name"配置屬性則任務失敗。 grunt.config.requires('meta.name'); // 如果缺少"mata.name"配置屬性則任務同樣失敗。 grunt.config.requires(['meta', 'name']); // 根據情況記錄日志。 grunt.log.writeln('This will only log if meta.name is defined in the config.'); });
為什么我的異步task沒有完成?
如果發生這種情況,可能是由於你忘記調用 this.async 方法來告訴Grunt你的任務是異步的。為了簡單起見,Grunt使用同步的編碼風格,可以在task體中通過調用 this.async() 將其轉換為異步的。
注意,傳遞 false 給 done() 函數就會告訴Grunt你的任務已經失敗。
例如:
grunt.registerTask('asyncme', 'My asynchronous task.', function() { var done = this.async(); setTimeout(function() {
done(false); //代表asyncme任務失敗
}, 1000); });
加油!