任務(wù)是Grunt的面包和奶油。就像你常用的工具,如: jshint
或 nodeunit
。每當(dāng)運(yùn)行Grunt時(shí), 你可以為其指定一個(gè)或多個(gè)任務(wù), 這些任務(wù)用于告訴Grunt你想要它做什么事情。
如果你沒(méi)有指定一個(gè)任務(wù),并且你已經(jīng)定義一個(gè)名為 "default" 的任務(wù),那么該任務(wù)將會(huì)默認(rèn)被執(zhí)行(不用詫異,總要做點(diǎn)兒什么?。。?/p>
如果指定了一個(gè)任務(wù)列表,新任務(wù)將是這一個(gè)或多個(gè)指定任務(wù)的別名。當(dāng)運(yùn)行此 "任務(wù)別名" 時(shí),在taskList
中指定的每個(gè)任務(wù)都會(huì)按照其出現(xiàn)的順序依次執(zhí)行。taskList
參數(shù)必須時(shí)一個(gè)任務(wù)數(shù)組。
grunt.registerTask(taskName, [description, ] taskList)
下面的任務(wù)別名案例中定義了一個(gè) 'default' 任務(wù),如果運(yùn)行Grunt時(shí)沒(méi)有指定任何任務(wù),它將自動(dòng)執(zhí)行'jshint'、'qunit'、'concat' 和 'uglify' 任務(wù)。
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
還可以給任務(wù)指定參數(shù)。在下面的案例中,別名 "dist" 將執(zhí)行 "concat" 和 "uglify" 兩個(gè)任務(wù),并且它們都帶有一個(gè) "dist" 參數(shù):
grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);
當(dāng)運(yùn)行一個(gè)多任務(wù)時(shí),Grunt會(huì)自動(dòng)從項(xiàng)目的配置對(duì)象中查找同名屬性。多任務(wù)可以有多個(gè)配置,并且可以使用任意命名的'targets'。
同時(shí)指定像grunt concat:foo
或者grunt concat:bar
這樣的任務(wù)和目標(biāo),在運(yùn)行時(shí)Grunt只會(huì)處理指定目標(biāo)的配置;然而如果運(yùn)行grunt concat
,將會(huì)遍歷所有的目標(biāo), 并按任務(wù)指定的順序處理每個(gè)目標(biāo)。注意,如果一個(gè)任務(wù)已經(jīng)使用grunt.task.renameTask重命名過(guò),Grunt將會(huì)自動(dòng)在配置對(duì)象中查找新任務(wù)名稱屬性。
大部分的contrib任務(wù)(主要是指官方提供的任務(wù)),包括grunt-contrib-jshint插件的jshint任務(wù),以及grunt-contrib-concat插件的concat任務(wù)都是多任務(wù)形式的。
grunt.registerMultiTask(taskName, [description, ] taskFunction)
對(duì)于指定的配置,這里有一個(gè)案例演示了如果通過(guò)grunt log:foo
運(yùn)行Grunt,它會(huì)輸出foo: 1,2,3
;如果通過(guò)grunt log:bar
來(lái)運(yùn)行Grunt, 它會(huì)輸出bar: hello world
。然而如果通過(guò)grunt log
運(yùn)行Grunt, 它會(huì)輸出foo: 1,2,3
,然后是bar: hello world
,最后是baz: false
(任務(wù)目標(biāo)會(huì)按照指定的順序進(jìn)行處理)。
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);
});
當(dāng)一個(gè)基本任務(wù)執(zhí)行時(shí),Grunt并不會(huì)檢查配置和環(huán)境 -- 它僅僅執(zhí)行指定的任務(wù)函數(shù),并傳遞任何使用冒號(hào)分割的參數(shù)作為函數(shù)的參數(shù)。
grunt.registerTask(taskName, [description, ] taskFunction)
下面的案例中,如果執(zhí)行 grunt foo:testing:123
,將輸出日志 foo, testing 123
。 如果執(zhí)行這個(gè)任務(wù)時(shí)不傳遞參數(shù),只是執(zhí)行 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);
}
});
你可以和任務(wù)一起瘋狂。如果你的任務(wù)并沒(méi)有遵循 "多任務(wù)" 結(jié)構(gòu),那就使用自定義任務(wù)。
grunt.registerTask('default', 'My "default" task description.', function() {
grunt.log.writeln('Currently running the "default" task.');
});
在一個(gè)任務(wù)內(nèi)部,你可以執(zhí)行其他的任務(wù)。
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']);
});
任務(wù)也可以是異步的。
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);
});
任務(wù)也可以訪問(wèn)它們自身名稱和參數(shù)。
grunt.registerTask('foo', 'My "foo" task.', function(a, b) {
grunt.log.writeln(this.name, a, b);
});
// 用法:
// grunt foo foo:bar
// logs: "foo", undefined, undefined
// logs: "foo", "bar", undefined
// grunt foo:bar:baz
// logs: "foo", "bar", "baz"
如果記錄到任何錯(cuò)誤,那么任務(wù)就會(huì)失敗。
grunt.registerTask('foo', 'My "foo" task.', function() {
if (failureOfSomeKind) {
grunt.log.error('This is an error message.');
}
// 如果這個(gè)任務(wù)出現(xiàn)錯(cuò)誤則返回false
if (ifErrors) { return false; }
grunt.log.writeln('This is the success message');
});
當(dāng)任務(wù)失敗時(shí),所有后續(xù)任務(wù)都將終止,除非指定 --force
。
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);
});
任務(wù)還可以依賴于其他任務(wù)的成功執(zhí)行。注意 grunt.task.requires
并不會(huì)真正的運(yùn)行其他任務(wù),它僅僅檢查其它任務(wù)是否已經(jīng)執(zhí)行,并且沒(méi)有失敗。
grunt.registerTask('foo', 'My "foo" task.', function() {
return false;
});
grunt.registerTask('bar', 'My "bar" task.', function() {
// 如果"foo"任務(wù)運(yùn)行失敗或者沒(méi)有運(yùn)行則任務(wù)失敗。
grunt.task.requires('foo');
// 如果"foo"任務(wù)運(yùn)行成功則執(zhí)行這里的代碼。
grunt.log.writeln('Hello, world.');
});
// 用法:
// grunt foo bar
// 沒(méi)有輸出,因?yàn)?quot;foo"失敗。
// grunt bar
// 沒(méi)有輸出,因?yàn)?quot;foo"從未運(yùn)行。
如果任務(wù)需要的配置屬性不存在,其也可能失敗。
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.');
});
任務(wù)還可以訪問(wèn)配置屬性。
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']));
});
在 contrib tasks 中可以查看更多案例。
通過(guò) process.env
來(lái)訪問(wèn)環(huán)境變量。
請(qǐng)參考 使用命令行工具章節(jié),查看完整的的命令行選項(xiàng)列表。
如果發(fā)生這種情況,可能是由于你忘記調(diào)用 this.async 方法來(lái)告訴Grunt你的任務(wù)是異步的。為了簡(jiǎn)單起見(jiàn),Grunt使用同步的編碼風(fēng)格,可以在task體中通過(guò)調(diào)用 this.async()
將其轉(zhuǎn)換為異步的。
注意,傳遞 false
給 done()
函數(shù)就會(huì)告訴Grunt你的任務(wù)已經(jīng)失敗。
例如:
grunt.registerTask('asyncme', 'My asynchronous task.', function() {
var done = this.async();
doSomethingAsync(done);
});
如果你需要更多參考資料來(lái)創(chuàng)建自己的 task ,請(qǐng)參考 API 文檔
更多建議: