如何一个接一个地顺序运行Gulp任务

时间:2014-04-02 22:45:35

标签: javascript node.js coffeescript gulp

在这样的代码片段中:

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并在完成后运行其他内容。但我无法弄明白。这件作品不起作用。请指教。

15 个答案:

答案 0 :(得分:406)

默认情况下,gulp会同时运行任务,除非它们具有显式依赖关系。这对于clean等您不想依赖的任务非常有用,但是您需要它们才能在其他任何事情之前运行。

我专门写了the run-sequence plugin以解决这个问题。安装后,使用它:

var runSequence = require('run-sequence');

gulp.task('develop', function(done) {
    runSequence('clean', 'coffee', function() {
        console.log('Run something else');
        done();
    });
});

您可以阅读自述包README上的完整说明 - 它还支持同时运行一些任务集。

请注意,这将是(effectively) fixed in the next major release of gulp,因为它们完全取消了自动依赖关系排序,并提供类似于run-sequence的工具,允许您手动指定运行顺序。

但是,这是一个重大的突破性变化,所以没有理由等到今天你可以使用run-sequence

答案 1 :(得分:370)

可以在gulp文档中找到解决此问题的唯一方法here

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']);

答案 2 :(得分:108)

它尚未正式发布,但即将推出的Gulp 4.0可让您轻松地与gulp.series进行同步任务。你可以这样做:

gulp.task('develop', gulp.series('clean', 'coffee'))

我发现了一篇很好的博客文章,介绍了如何升级和利用这些简洁的功能:  migrating to gulp 4 by example

答案 3 :(得分:53)

我使用generator-gulp-webapp Yeoman生成器生成了一个node / gulp app。它处理了"干净的难题"这样(转换为问题中提到的原始任务):

gulp.task('develop', ['clean'], function () {
  gulp.start('coffee');
});

答案 4 :(得分:31)

run-sequence是最明确的方式(至少在Gulp 4.0发布之前)

使用运行顺序,您的任务将如下所示:

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有意无证,因为它可能导致复杂的构建文件,我们不希望有人使用它

(来源:https://github.com/gulpjs/gulp/issues/426#issuecomment-41208007

答案 5 :(得分:26)

根据Gulp文档:

  

在依赖项完成之前,您的任务是否正在运行?确保您的依赖项任务正确使用异步运行提示:接受回调或返回承诺或事件流。

同步运行您的任务序列:

  1. 将事件流(例如gulp.src)返回gulp.task以通知 流结束时的任务。
  2. gulp.task的第二个参数中声明任务依赖项。
  3. 参见修订后的代码:

    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"
    

答案 6 :(得分:9)

我遇到了同样的问题,解决方案对我来说非常简单。基本上将您的代码更改为以下,它应该工作。注意: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"

答案 7 :(得分:7)

尝试了所有提出的解决方案,似乎都有自己的问题。

如果您实际查看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" ));

答案 8 :(得分:3)

只需coffee取决于clean,而develop取决于coffee

gulp.task('coffee', ['clean'], function(){...});
gulp.task('develop', ['coffee'], function(){...});

现在发送的是序列号:cleancoffeedevelop。请注意,clean的实施和coffee的实施必须接受回调,"so the engine knows when it'll be done"

gulp.task('clean', function(callback){
  del(['dist/*'], callback);
});

总之,下面是同步clean简单gulp模式,后跟异步构建依赖

//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非常聪明,每clean只运行一次build,无论build依赖项中有多少依赖于clean。如上所述,clean是同步障碍,然后所有build的依赖项并行运行,然后运行build

答案 9 :(得分:3)

我正在寻找这个答案一段时间。现在我在官方的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));
});

答案 10 :(得分:3)

对我来说,连接后没有运行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']); 

来源http://schickling.me/synchronous-tasks-gulp/

答案 11 :(得分:2)

Gulp和Node使用承诺

所以你可以这样做:

// ... 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.all()来获得一个在所有promises解析时触发的回调。

答案 12 :(得分:0)

要等任务是否完成然后再休息,我是这样的:

gulp.task('default',
  gulp.series('set_env', gulp.parallel('build_scss', 'minify_js', 'minify_ts', 'minify_html', 'browser_sync_func', 'watch'),
    function () {
    }));

荣誉:https://fettblog.eu/gulp-4-parallel-and-series/

答案 13 :(得分:0)

我发现一个接一个地执行任务的非常简单有效的解决方案(当一个任务完成时,将启动第二个任务)(仅提供一个示例)是:
gulp.task('watch', () =>
gulp.watch(['src/**/*.css', 'src/**/*.pcss'], gulp.series('build',['copy'])) );
这意味着当您需要在 first-task 之前运行 second-task 时,您需要将第二个任务(在本例中为copy)写在方括号中。
注意
任务的外部应该有圆括号(直到您希望它们同时发生)

答案 14 :(得分:-8)

试试这个黑客:-) 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

查看帖子!