GulpTask
建立任務
- Gulp 裡的一個任務即為一個JavaScript函式
- 函式的參數通常為一個可回呼(Call Back)的函式
- 回傳值通常是stream、promise、event emitter、child process 或 observable
任務類型
- 公開任務(Public tasks)
- 可以用 gulp 命令直接呼叫
- 在 gulpfile 中要 export
- 私有任務(Private tasks)
- 在內部使用
- 通常作用來給series()或parallel()使用
例: 公開任務及私有任務
const { series } = require('gulp');
// 公開函式(有被export)可以被 gulp 指令直接叫用,也可以被用在series()中
function build(cb) {
// body omitted
cb();
}
// 私有函式(沒有被export)
function clean(cb) {
// body omitted
cb();
}
exports.build = build; // 導出 build
exports.default = series(clean, build);
組合任務
- 將獨立的任務組合成一組任務
- 可以用
series()
和 parallel()
- series() : 任務按順序執行
- parallel() : 任務盡可能同時一起執行(平行處理)
series()
和 parallel()
可以互相巢狀使用到任意深度
例: 循序執行 series()
const { series } = require('gulp');
function transpile(cb) { /* 省略 */ cb(); }
function bundle(cb) { /* 省略 */ cb(); }
}
exports.build = series(transpile, bundle);
例: 平行處理 parallel()
const { parallel } = require('gulp');
function javascript(cb) { /* 省略 */ cb(); }
function css(cb) { /* 省略 */ cb(); }
exports.build = parallel(javascript, css);
例: series()與paralle()互相巢狀使用
const { series, parallel } = require('gulp');
function clean(cb) { /* 省略 */ cb(); }
function cssTranspile(cb) { /* 省略 */ cb(); }
function cssMinify(cb) { /* 省略 */ cb(); }
function jsTranspile(cb) { /* 省略 */ cb(); }
function jsBundle(cb) { /* 省略 */ cb(); }
function jsMinify(cb) { /* 省略 */ cb(); }
function publish(cb) { /* 省略 */ cb(); }
exports.build = series(
clean,
parallel(
cssTranspile,
series(jsTranspile, jsBundle)
),
parallel(cssMinify, jsMinify),
publish
);
例: 錯誤的寫法
- 在組合任務中,如果有多個任務叫用同一個任務(Clean),可能會產生無法預估的結果
const { series, parallel } = require('gulp');
const clean = function(cb) { cb(); }
const css = series(clean, function(cb) { cb(); });
const javascript = series(clean, function(cb) { cb(); });
exports.build = parallel(css, javascript);
例: 重構 錯誤的寫法
- 用
series()
先執行clean任務,再同時執行css和javascript任務
- 也就是每個任務都寫成獨立的,不要呼叫其它任務
- 最後再由
exports.build
指定任務執行的順序
const { series, parallel } = require('gulp');
const clean = function(cb) { cb(); }
const css = function(cb) { cb(); }
const javascript = function(cb) { cb(); }
exports.build = series(clean, parallel(css, javascript));
任務(task)完成通知
- gulp不在支援非同步任務(Synchronous tasks)
- 當任務回傳 stream、promise、event emitter、child process 或 observable 時,gulp會看成功或錯誤來決定要繼續執行或結束執行
- 任務出錯時,gulp會立刻結束執行並顯示錯誤
- 任務組合出錯時
- series() : 任何一個任務出錯,整個任務組合都會結束
- parallel() : 任何一個任務出錯,整個任務組合都會結束 ⇒ 有的任務可能執行完,有的沒執行完
例: 任務(task)完成通知 - 使用 callback
- 如果任務沒有回傳任何內容,要呼叫cb()來讓gulp知道任務已經結束
function callbackTask(cb) { cb(); /* 在非同步執行時,要呼叫cb() */ }
exports.default = callbackTask;
- 可以用 Error 當作cb的參數,告訴 gulp 任務的錯誤
function callbackError(cb) {
cb(new Error('kaboom'));
}
exports.default = callbackError;
- 通常會將cb傳給另一個API,而不是自己呼叫cb()
const fs = require('fs');
function passingCallback(cb) {
fs.access('gulpfile.js', cb);
}
exports.default = passingCallback;
例: 任務(task)完成通知 - 回傳 stream
const { src, dest } = require('gulp');
function streamTask() { return src('*.js').pipe(dest('output')); }
exports.default = streamTask;
例: 任務(task)完成通知 - 回傳 promise
function promiseTask() { return Promise.resolve('the value is ignored'); }
exports.default = promiseTask;
例: 任務(task)完成通知 - event emitter
const { EventEmitter } = require('events');
function eventEmitterTask() {
const emitter = new EventEmitter();
setTimeout(() => emitter.emit('finish'), 250); // Emit has to happen async otherwise gulp isn't listening yet
return emitter;
}
exports.default = eventEmitterTask;
例: 任務(task)完成通知 - child process
const { exec } = require('child_process');
function childProcessTask() { return exec('date'); }
exports.default = childProcessTask;
例: 任務(task)完成通知 - observable
const { Observable } = require('rxjs');
function observableTask() { return Observable.of(1, 2, 3); }
exports.default = observableTask;