Gulp:如何按顺序组合任务?

7

我需要通过按顺序处理不同的资源来组成gulp任务,因为它们之间存在依赖关系。

根据文档,应该通过合并流来实现,但我不知道如何强制排序和串行化。

在Gulp 3中,该如何正确地建模呢?

我通常将函数用作单个构建步骤的容器,然后从构建和监视任务中调用它们:

function buildModule(module) {
    var streams = [];

    // step one
    streams.push(
        gulp.src(path.join('./modules', module, '*.js'))
        // ... series of chained calls
    );

    // step two
    streams.push(
        gulp.src([TMP, ...])
        // generate target also using some of the files from step one
        );

    return eventStream.merge(streams);
}

gulp.task('build:A', [], function () {
    return buildModule('A');
});

gulp.task('watch:buildModule', [], function () {
    gulp.watch('./modules/**/*.js', function (event) {
        if (event.type === 'changed') {
            return buildModule(path.basename(path.dirname(event.path)));
        }
    });
});

gulp.task('default', ['watch:buildModule'], function () {});

1
@materialdreams 你不是可以直接将一个流的结果 .pipe 到依赖于它的另一个流吗?为什么需要手动管理同步? - Asad Saeeduddin
@Asad 为了简单起见,我使用了注释“// ...生成TMP”作为一系列链接调用的占位符,这些调用在第一步中生成临时文件集。第二步然后使用第一步生成的一些文件和其他文件作为源,并使用完全不同的一系列链接调用来生成最终目标文件。 - doberkofler
@materialdreams 好的,所以你有一系列文件流经了一些预处理。我们称之为 var stage1_1 = gulp.src(...).pipe(foo()).pipe(bar())...。你想要使用来自 stage1_1 流的文件,以及来自其他并行工作的文件,并将它们全部通过一些步骤。你可以这样做 var stage1_2 = gulp.src("./myauxilaryfiles/*.*").pipe(some()).pipe(more()).pipe(processing())。最后 var final = merge(stage1_1, stage1_2).pipe(my()).pipe(final()).pipe(processing());。这里的 mergevar merge = require('merge-stream'); - Asad Saeeduddin
@asad 我不确定我理解了。让我们继续使用我的示例,其中包括合并在内的所有内容都按预期工作,除了步骤2不等待步骤1完成的事实。我该如何强制执行? - doberkofler
@materialdreams 你不能同时拥有多个流并期望它们是顺序的。在你的例子中,不要将第一个流添加到streams中,而是将其存储在变量中。然后,创建另一个流来表示你想要传递到step2的额外文件。现在,你需要合并这两个流并将它们传递到第二阶段。你需要引入merge-stream模块,并调用你得到的函数与前面提到的两个流。然后,在这个合并的流上进行所有的stage2处理。希望这样说得通? - Asad Saeeduddin
显示剩余3条评论
2个回答

16

基本上有三种方法可以做到这一点。

1. 定义依赖任务

Gulp允许开发人员通过将任务名称数组作为第二个参数传递来定义依赖任务:

gulp.task('concat', function () {
    // ...
});

gulp.task('uglify', ['concat'], function () {
    // ...
});

gulp.task('test', ['uglify'], function () {
    // ...
});

// Whenever you pass an array of tasks each of them will run in parallel.
// In this case, however, they will run sequentially because they depend on each other
gulp.task('build', ['concat', 'uglify', 'test']);

2. 使用 run-sequence

你也可以使用 run-sequence 来按顺序运行一组任务:

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

gulp.task('build', function (cb) {
    runSequence('concat', 'uglify', 'test', cb);
});

3. 使用lazypipe

虽然Lazypipe是一个用于创建可重用管道的库,但您也可以使用它来创建顺序任务。例如:

var preBuildPipe = lazypipe().pipe(jshint);
var buildPipe = lazypipe().pipe(concat).pipe(uglify);
var postBuildPipe = lazypipe().pipe(karma);

gulp.task('default', function () {
    return gulp.src('**/*.js')
        .pipe(preBuildPipe)
        .pipe(buildPipe)
        .pipe(postBuildPipe)
        .pipe(gulp.dest('dist'));
});

选项1和2显然是在使用任务组合任务时的最佳选择,但这并不是我实际要寻找的。对我来说,任务的粒度很重要,在我的用例中,我将最终拥有大量(私有)任务,而不是使用流组合任务,然后让任务执行它们应该执行的操作。 选项3看起来很有前途,但stream-series似乎是我尝试做的事情的更简单的解决方案。 谢谢! - doberkofler

3
这个小模块可能会有所帮助:stream-series。只需将eventStream.merge(streams)替换为:
var series = require('stream-series');
// ...
return series(streams);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接