Task는 Grunt의 존재 이유이자 가장 중요한 개념이다. 여러분이 하는 대부분의 일(task)은 jshint나 nodeunit같은 것들이다. 실행할 Task를 하나 이상 명시해서 Grunt에게 하고 싶은 일이 무엇인지 알려주면, Grunt가 그 일을 매번 실행한다.
여러분이 task를 새로 명시하지 않았고, "default"란 이름의 task가 이미 정의되어 있다면, 기본값으로 그 task가 실행된다.
다음처럼 새로운 task에 다른 task 명단을 명시하면, 그 신규 task의 이름은 여러 task들을 대표하는 별명(alias)이 된다. 이런 "alias task"가 실행될 때면, taskList에 명시한 모든 task들이 순서대로 실행된다. 이때 taskList 전달인자는 배열이다.
grunt.registerTask(taskName, [description, ] taskList)다음 예제는 Grunt를 특정 task 지정없이 grunt로 실행할 때 자동으로 "jshint", "qunit", "concat", "uglify" task들을 실행하는 "default"라는 alias task다.
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);Task 전달인자를 다음처럼 지정할 수도 있다. "dist"라는 alias task는 "concat"과 "uglify"에서 "dist" target 들만 실행한다.
grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);Multi-task로 만든 task는 실행될 때, Grunt 환경 설정 객체에서 동명의 프로퍼티를 찾는다. 또한 multi-task는 적절한 target(task의 하위 개념) 명으로 각자의 환경설정을 가질 수 있다.
grunt concat란 컴멘드가 그 안의 모든 target를 순회하는 반면에, grunt concat:foo나 grunt concat:bar처럼 task와 target까지 지정하면, 특정 target의 환경설정만 가져온다. 이때 grunt.task.renameTask로 이름을 변경하면, 바꾼 task 명으로 환경 설정을 찾는다.
grunt-contrib-jshint plugin jshint task와 grunt-contrib-concat plugin concat task같이 contrib로 시작하는 대부분의 task는 multi task다.
grunt.registerMultiTask(taskName, [description, ] taskFunction)다음 multi-task에서 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.initConfig({
log: {
foo: [1, 2, 3],
bar: 'hello world',
baz: false
}
});
grunt.registerMultiTask('log', 'Log stuff.', function() {
grunt.log.writeln(this.target + ': ' + this.data);
});Multi-task가 아닌 기본 task가 실행될 때는 Grunt가 환경설정을 바라보지 않는다. 지정한 task function만 실행한다. 기본 task에서는 콜론(:)로 구분한 인자 목록을 task function 함수의 전달인자로 넘길 수 있다.
grunt.registerTask(taskName, [description, ] taskFunction)grunt foo:testing:123를 입력하면 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);
}
});만들려는 Task가 "multi-task" 구조를 따르지 않는다면 기본 task형태로 사용자 정의 task를 만들자.
grunt.registerTask('default', 'My "default" task description.', function() {
grunt.log.writeln('Currently running the "default" task.');
});task 안에서 다른 task를 실행할 수 있으며,
grunt.registerTask('foo', 'My "foo" task.', function() {
// "bar"와 "baz" task가 "foo" 가 끝난 후에 순서대로 실행하려고 대기중이다.
grunt.task.run('bar', 'baz');
// 이렇게 적어도 된다.
grunt.task.run(['bar', 'baz']);
});비동기도 가능하다.
grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() {
// task를 비동기 모드로 만들고 "done" 함수로 제어한다.
var done = this.async();
// 동기 작업을 실행한다.
grunt.log.writeln('Processing task...');
// 그리고 비동기 작업을 실행한다.
setTimeout(function() {
grunt.log.writeln('All done!');
done();
}, 1000);
});이렇게 만든 task도 그 이름과 인자를 사용해서 접근할 수 있다.
grunt.registerTask('foo', 'My "foo" task.', function(a, b) {
grunt.log.writeln(this.name, a, b);
});
// 사용법:
// grunt foo foo:bar
// 출력로그: "foo", undefined, undefined
// 출력로그: "foo", "bar", undefined
// grunt foo:bar:baz
// 출력로그: "foo", "bar", "baz"Task에서 에러가 발생하면 Task를 실패처리 할 수도 있다.
grunt.registerTask('foo', 'My "foo" task.', function() {
if (failureOfSomeKind) {
grunt.log.error('에러 메세지');
}
// task 실행 중 에러가 있다면 false를 반환해서 실패 처리한다.
if (ifErrors) { return false; }
grunt.log.writeln('성공 메세지');
});task가 실패하면, --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);
});Task는 다른 task가 성공적으로 실행되었는지 여부와 관련지을 수도 있다. grunt.task.requires는 실제로 다른 task를 실행하지는 않지만, 그 task가 실행되었는지, 실패는 없었는지를 확인한다.
grunt.registerTask('foo', 'My "foo" task.', function() {
return false;
});
grunt.registerTask('bar', 'My "bar" task.', function() {
// "foo" task가 실패했거나 실행된적이 없다면, 이 task를 실패 처리한다.
grunt.task.requires('foo');
// 이 코드는 "foo" task가 성공적으로 실행된 적이 있을 때만 실행된다.
grunt.log.writeln('Hello, world.');
});
// 사용법
// grunt foo bar
// foo가 실패하는 task이므로 로그는 출력되지 않는다.
// grunt bar
// foo가 실행된적이 없으므로 로그는 출력되지 않는다.grunt.config.requires를 사용하면, Task가 존재하지 않는 환경설정 프로퍼티를 요구할 때, 실패 처리할 수 있다.
grunt.registerTask('foo', 'My "foo" task.', function() {
// "meta.name" 란 환경설정 프로퍼티가 없으면 이 타스트를 실패 처리한다.
grunt.config.requires('meta.name');
// 이경우도 "meta.name" 환경설정 프로퍼티가 없다면, 실패한다.
grunt.config.requires(['meta', 'name']);
// 조건이 충족되어야 로그가 출력된다.
grunt.log.writeln('meta.name이 환경설정에 정의되어있을 때만 로그가 출력된다.');
});환경설정 프로퍼티에는 grunt.config로 접근할 수 있다.
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 task들을 참고하자.
내용 없음.
비동기 task를 짰는데 완료되지 않는다면, 대부분 this.asynce를 호출하지 않았기 때문이다. 쉽게 하려면, 동기식 코딩 스타일을 사용하고 나서 task 내부에 this.async()를 호출해서 비동기로 변경할 수 있다.
그리고 다시 말하지만, done()에 인자로 false를 넘기면 Grunt에게 task가 실패했다고 알릴 수 있다.
예제 코드다.
grunt.registerTask('asyncme', 'My asynchronous task.', function() {
var done = this.async();
doSomethingAsync(done);
});