[英]How to run Gulp tasks sequentially one after the other
在這樣的片段中:
gulp.task "coffee", ->
gulp.src("src/server/**/*.coffee")
.pipe(coffee {bare: true}).on("error",gutil.log)
.pipe(gulp.dest "bin")
gulp.task "clean",->
gulp.src("bin", {read:false})
.pipe clean
force:true
gulp.task 'develop',['clean','coffee'], ->
console.log "run something else"
在develop
任務中,我想clean
地運行,完成后,運行coffee
,完成后,運行其他東西。 但我想不通。 這一段不行。 請指教。
默認情況下,gulp 同時運行任務,除非它們有明確的依賴關系。 這對於像clean
這樣的任務不是很有用,在那里你不想依賴,但你需要它們在其他一切之前運行。
我專門編寫了run-sequence
插件來解決 gulp 的這個問題。 安裝后,像這樣使用它:
var runSequence = require('run-sequence');
gulp.task('develop', function(done) {
runSequence('clean', 'coffee', function() {
console.log('Run something else');
done();
});
});
您可以閱讀包 README 上的完整說明——它還支持同時運行一些任務集。
請注意,這將在 gulp 的下一個主要版本中(有效地)修復,因為它們完全消除了自動依賴排序,並提供了類似於run-sequence
工具,允許您手動指定所需的運行順序。
然而,這是一個重大的突破性變化,所以沒有理由等待今天可以使用run-sequence
。
這個問題唯一好的解決方案可以在 gulp 文檔中找到:
var gulp = require('gulp');
// takes in a callback so the engine knows when it'll be done
gulp.task('one', function(cb) {
// do stuff -- async or otherwise
cb(err); // if err is not null and not undefined, the orchestration will stop, and 'two' will not run
});
// identifies a dependent task must be complete before this one begins
gulp.task('two', ['one'], function() {
// task 'one' is done now
});
gulp.task('default', ['one', 'two']);
// alternatively: gulp.task('default', ['two']);
它尚未正式發布,但即將推出的 Gulp 4.0 可讓您輕松地使用 gulp.series 執行同步任務。 你可以簡單地這樣做:
gulp.task('develop', gulp.series('clean', 'coffee'))
我找到了一篇很好的博客文章,介紹了如何升級和利用這些簡潔的功能:通過示例遷移到 gulp 4
我使用generator-gulp-webapp Yeoman 生成器生成了一個節點/gulp 應用程序。 它以這種方式處理了“干凈的難題”(轉換為問題中提到的原始任務):
gulp.task('develop', ['clean'], function () {
gulp.start('coffee');
});
run-sequence是最清晰的方式(至少在 Gulp 4.0 發布之前)
使用 run-sequence ,您的任務將如下所示:
var sequence = require('run-sequence');
/* ... */
gulp.task('develop', function (done) {
sequence('clean', 'coffee', done);
});
但是如果你(出於某種原因)不想使用它, gulp.start
方法會有所幫助:
gulp.task('develop', ['clean'], function (done) {
gulp.on('task_stop', function (event) {
if (event.task === 'coffee') {
done();
}
});
gulp.start('coffee');
});
注意:如果你只開始任務而不聽結果, develop
任務會比coffee
更早完成,這可能會造成混淆。
您也可以在不需要時刪除事件偵聽器
gulp.task('develop', ['clean'], function (done) {
function onFinish(event) {
if (event.task === 'coffee') {
gulp.removeListener('task_stop', onFinish);
done();
}
}
gulp.on('task_stop', onFinish);
gulp.start('coffee');
});
考慮到您可能還想收聽task_err
事件。 task_stop
在成功完成時觸發,而task_err
在出現錯誤時出現。
您可能還想知道為什么gulp.start()
沒有官方文檔。 gulp 成員的這個回答解釋了這些事情:
gulp.start
是gulp.start
沒有記錄的,因為它會導致復雜的構建文件,我們不希望人們使用它
(來源:https ://github.com/gulpjs/gulp/issues/426#issuecomment-41208007 )
根據 Gulp 文檔:
您的任務是否在依賴項完成之前運行? 確保您的依賴任務正確使用異步運行提示:接收回調或返回承諾或事件流。
要同步運行您的任務序列:
gulp.src
)返回給gulp.task
以通知任務流何時結束。gulp.task
的第二個參數中聲明任務依賴gulp.task
。查看修改后的代碼:
gulp.task "coffee", ->
return gulp.src("src/server/**/*.coffee")
.pipe(coffee {bare: true}).on("error",gutil.log)
.pipe(gulp.dest "bin")
gulp.task "clean", ['coffee'], ->
return gulp.src("bin", {read:false})
.pipe clean
force:true
gulp.task 'develop',['clean','coffee'], ->
console.log "run something else"
我遇到了完全相同的問題,結果對我來說解決方案非常簡單。 基本上將您的代碼更改為以下內容,它應該可以工作。 注意:gulp.src 之前的返回對我來說完全不同。
gulp.task "coffee", ->
return gulp.src("src/server/**/*.coffee")
.pipe(coffee {bare: true}).on("error",gutil.log)
.pipe(gulp.dest "bin")
gulp.task "clean",->
return gulp.src("bin", {read:false})
.pipe clean
force:true
gulp.task 'develop',['clean','coffee'], ->
console.log "run something else"
嘗試了所有提出的解決方案,似乎都有自己的問題。
如果您實際查看 Orchestrator 源代碼,尤其是.start()
實現,您會發現如果最后一個參數是一個函數,它會將其視為回調。
我為我自己的任務寫了這個片段:
gulp.task( 'task1', () => console.log(a) )
gulp.task( 'task2', () => console.log(a) )
gulp.task( 'task3', () => console.log(a) )
gulp.task( 'task4', () => console.log(a) )
gulp.task( 'task5', () => console.log(a) )
function runSequential( tasks ) {
if( !tasks || tasks.length <= 0 ) return;
const task = tasks[0];
gulp.start( task, () => {
console.log( `${task} finished` );
runSequential( tasks.slice(1) );
} );
}
gulp.task( "run-all", () => runSequential([ "task1", "task2", "task3", "task4", "task5" ));
我一直在尋找這個答案。 現在我在官方的 gulp 文檔中得到了它。
如果你想在最后一個任務完成時執行 gulp 任務,你必須返回一個流:
gulp.task('wiredep', ['dev-jade'], function () { var stream = gulp.src(paths.output + '*.html') .pipe($.wiredep()) .pipe(gulp.dest(paths.output)); return stream; // execute next task when this is completed }); // First will execute and complete wiredep task gulp.task('prod-jade', ['wiredep'], function() { gulp.src(paths.output + '**/*.html') .pipe($.minifyHtml()) .pipe(gulp.dest(paths.output)); });
簡單地做coffee
靠clean
, develop
靠coffee
:
gulp.task('coffee', ['clean'], function(){...});
gulp.task('develop', ['coffee'], function(){...});
Dispatch 現在是連續的: clean
→ coffee
→ develop
。 請注意, clean
的實現和coffee
的實現必須接受回調, “因此引擎知道何時完成” :
gulp.task('clean', function(callback){
del(['dist/*'], callback);
});
總之,下面是一個簡單的 gulp 模式,用於同步clean
后跟異步構建依賴項:
//build sub-tasks
gulp.task('bar', ['clean'], function(){...});
gulp.task('foo', ['clean'], function(){...});
gulp.task('baz', ['clean'], function(){...});
...
//main build task
gulp.task('build', ['foo', 'baz', 'bar', ...], function(){...})
Gulp 足夠聰明,每次build
運行一次clean
,無論build
的依賴項有多少依賴於clean
。 如上所述, clean
是一個同步障礙,然后所有build
的依賴項並行運行,然后build
運行。
對我來說,它沒有在連接后運行 minify 任務,因為它期望連接輸入並且它沒有生成幾次。
我嘗試按執行順序添加到默認任務,但沒有奏效。 它在為每個任務添加一個return
並在gulp.start()
獲得縮小后工作,如下所示。
/**
* Concatenate JavaScripts
*/
gulp.task('concat-js', function(){
return gulp.src([
'js/jquery.js',
'js/jquery-ui.js',
'js/bootstrap.js',
'js/jquery.onepage-scroll.js',
'js/script.js'])
.pipe(maps.init())
.pipe(concat('ux.js'))
.pipe(maps.write('./'))
.pipe(gulp.dest('dist/js'));
});
/**
* Minify JavaScript
*/
gulp.task('minify-js', function(){
return gulp.src('dist/js/ux.js')
.pipe(uglify())
.pipe(rename('ux.min.js'))
.pipe(gulp.dest('dist/js'));
});
gulp.task('concat', ['concat-js'], function(){
gulp.start('minify-js');
});
gulp.task('default',['concat']);
Gulp 和 Node 使用promises 。
所以你可以這樣做:
// ... require gulp, del, etc
function cleanTask() {
return del('./dist/');
}
function bundleVendorsTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest('...'));
}
function bundleAppTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest('...'));
}
function tarTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest('...'));
}
gulp.task('deploy', function deployTask() {
// 1. Run the clean task
cleanTask().then(function () {
// 2. Clean is complete. Now run two tasks in parallel
Promise.all([
bundleVendorsTask(),
bundleAppTask()
]).then(function () {
// 3. Two tasks are complete, now run the final task.
tarTask();
});
});
});
如果返回 gulp 流,則可以使用then()
方法添加回調。 或者,您可以使用 Node 的原生Promise
來創建您自己的Promise
。 在這里,我使用Promise.all()
來實現一個回調,當所有Promise.all()
都解決時會觸發該回調。
等待看看任務是否完成,然后剩下的,我是這樣的:
gulp.task('default',
gulp.series('set_env', gulp.parallel('build_scss', 'minify_js', 'minify_ts', 'minify_html', 'browser_sync_func', 'watch'),
function () {
}));
我發現一個接一個地執行任務的非常簡單有效的解決方案(當一個任務完成時,第二個任務將被啟動)(僅提供一個例子)是:
gulp.task('watch', () =>
gulp.watch(['src/**/*.css', 'src/**/*.pcss'], gulp.series('build',['copy'])) );
這意味着當您需要在second-task
first-task
之前運行first-task
,您需要將第二個任務(在這種情況下為copy
)寫在方括號中。
筆記
任務的外部應該有圓括號(直到您希望它們同時發生)
試試這個 hack :-) Gulp v3.x Hack for Async bug
我嘗試了自述文件中的所有“官方”方法,它們對我不起作用,但確實如此。 你也可以升級到 gulp 4.x 但我強烈建議你不要,它破壞了很多東西。 您可以使用真正的 js 承諾,但是,嘿,這是快速、骯臟、簡單的 :-) 基本上您使用:
var wait = 0; // flag to signal thread that task is done
if(wait == 0) setTimeout(... // sleep and let nodejs schedule other threads
看看帖子!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.