如何批量类似gulp任务以减少代码重复

时间:2015-03-30 03:15:19

标签: gulp gulp-concat

我编写了一个gulp文件,它监视多个目录以进行更改,然后创建连接到多个指定目标。

以下是我的项目结构的简化版本:

我有2个站点文件夹: 一个两个/

每个站点都有两个分支文件夹: a / b /

在每个分支内,有三个文件夹: 内部/ 外部网络/

我的任务是从内部和外部文件夹中获取类似的部分文件,并将它们连接到相关的Web文件夹中。以下是所需输出的简单示例。

-- inner/
 |-- color1
 |-- color2
 |-- fruit1
 |-- fruit2
-- outer/
 |-- color1
 |-- color2
 |-- fruit1
 |-- fruit2
-- web/
 |-- colors.txt
 |-- fruits.txt

我创建了一个 config.json 文件来保存特定于站点的配置。目前仅使用它来自定义站点路径。这是 config.json

{
  "sites": {
    "one": {
      "a": "/path/to/one/a/",
      "b": "/path/to/one/b/"
    },
    "two": {
      "a": "/path/to/two/a/",
      "b": "/path/to/two/b/"
    }
  }
}

最后这里是 gulpfile.js

// Include local Gulp
var gulp = require("gulp");

// Get data from config.json
var sites = require("./config.json").sites;

// Include Gulp specific plugins
var gConcat = require("gulp-concat");
var gHeader = require("gulp-header");
var gUtil = require("gulp-util");
var gNotify = require("gulp-notify");

// Setup directories
var outer = "outer/";
var inner = "inner/";
var web = "web/";

// Misc
var alertMessage = "# GENERATED FILE - DO NOT MODIFY\n\n";

// 8 total tasks for concatenation

// Concatenate to colors.txt - 4 tasks
// Color task 1: [ Site => one ] [ Branch => a ]
gulp.task("one_a_color", function() {
    return gulp.src([sites.one.a + outer + "color?", sites.one.a + inner + "color?"])
        .pipe(gConcat("colors.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.one.a + web))
        .pipe(gNotify());
});

// Color task 2: [ Site => one ] [ Branch => b ]
gulp.task("one_b_color", function() {
    return gulp.src([sites.one.b + outer + "color?", sites.one.b + inner + "color?"])
        .pipe(gConcat("colors.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.one.b + web))
        .pipe(gNotify());
});

// Color task 3: [ Site => two ] [ Branch => a ]
gulp.task("two_a_color", function() {
    return gulp.src([sites.two.a + outer + "color?", sites.two.a + inner + "color?"])
        .pipe(gConcat("colors.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.two.a + web))
        .pipe(gNotify());
});

// Color task 4: [ Site => two ] [ Branch => b ]
gulp.task("two_b_color", function() {
    return gulp.src([sites.two.b + outer + "color?", sites.two.b + inner + "color?"])
        .pipe(gConcat("colors.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.two.b + web))
        .pipe(gNotify());
});

// Concatenate to fruits.txt - 4 tasks
// Fruit task 1: [ Site => one ] [ Branch => a ]
gulp.task("one_a_fruit", function() {
    return gulp.src([sites.one.a + outer + "fruit?", sites.one.a + inner + "fruit?"])
        .pipe(gConcat("fruits.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.one.a + web))
        .pipe(gNotify());
});

// Fruit task 2: [ Site => one ] [ Branch => b ]
gulp.task("one_b_fruit", function() {
    return gulp.src([sites.one.b + outer + "fruit?", sites.one.b + inner + "fruit?"])
        .pipe(gConcat("fruits.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.one.b + web))
        .pipe(gNotify());
});

// Fruit task 3: [ Site => two ] [ Branch => a ]
gulp.task("two_a_fruit", function() {
    return gulp.src([sites.two.a + outer + "fruit?", sites.two.a + inner + "fruit?"])
        .pipe(gConcat("fruits.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.two.a + web))
        .pipe(gNotify());
});

// Fruit task 4: [ Site => two ] [ Branch => b ]
gulp.task("two_b_fruit", function() {
    return gulp.src([sites.two.b + outer + "fruit?", sites.two.b + inner + "fruit?"])
        .pipe(gConcat("fruits.txt"))
        .pipe(gHeader(alertMessage))
        .pipe(gulp.dest(sites.two.b + web))
        .pipe(gNotify());
});

// Watch for all events in specified {directories}/{files}, then trigger appropriate task
// 8 total watch jobs
gulp.task("watch", function () {
    // Color related watch jobs - Total 4
    // Color watch 1: [ Site => one ] [ Branch => a ]
    gulp.watch([sites.one.a + outer + "**/color?", sites.one.a + inner + "**/color?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("one_a_color");
    });

    // Color watch 2: [ Site => one ] [ Branch => b ]
    gulp.watch([sites.one.b + outer + "**/color?", sites.one.b + inner + "**/color?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("one_b_color");
    });

    // Color watch 3: [ Site => two ] [ Branch => a ]
    gulp.watch([sites.two.a + outer + "**/color?", sites.two.a + inner + "**/color?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("two_a_color");
    });

    // Color watch 4: [ Site => two ] [ Branch => b ]
    gulp.watch([sites.one.b + outer + "**/color?", sites.one.b + inner + "**/color?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("two_b_color");
    });

    // Fruit related watch jobs - Total 4
    // Fruit watch 1: [ Site => one ] [ Branch => a ]
    gulp.watch([sites.one.a + outer + "**/fruit?", sites.one.a + inner + "**/fruit?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("one_a_fruit");
    });

    // Fruit watch 2: [ Site => one ] [ Branch => b ]
    gulp.watch([sites.one.b + outer + "**/fruit?", sites.one.b + inner + "**/fruit?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("one_b_fruit");
    });

    // Fruit watch 3: [ Site => two ] [ Branch => a ]
    gulp.watch([sites.two.a + outer + "**/fruit?", sites.two.a + inner + "**/fruit?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("two_a_fruit");
    });

    // Fruit watch 4: [ Site => two ] [ Branch => b ]
    gulp.watch([sites.one.b + outer + "**/fruit?", sites.one.b + inner + "**/fruit?"], function(event) {
        gUtil.log(event.path.split("/").pop(), "=>", event.type);
        gulp.start("two_b_fruit");
    });
});

// Run all tasks
gulp.task("background",
    [
        "one_a_color", "one_b_color", "two_a_color", "two_b_color",
        "one_a_fruit", "one_b_fruit", "two_a_fruit", "two_b_fruit",
        "watch"
    ]
);

上面的gulp文件可以正常工作。但是,正如您所看到的,大多数代码都是重复的,只有更改的部分是gulp.src和gulp.dest,以及任务名称。

我的问题是。是否可以简化这个gulp文件,因此不是为每个任务重复代码,也许可以将类似的任务一起批处理。

1 个答案:

答案 0 :(得分:1)

不是那么容易的任务,但让我们看看我们是否可以优化它。 Gulp和Globs非常重视数组,这就是为什么我们必须首先将路径转换为数组:

var gulp = require('gulp');
var concat = require('gulp-concat');
var es = require('event-stream');

var sites = require('./config.json').sites;

var toArray = function(conf) {
    var arr = [];
    for(var key in conf) {
        if(typeof conf[key] === 'object') {
            arr = arr.concat(toArray(conf[key]));
        } else {
            arr.push(conf[key]);
        }
    }
    return arr;
};

var sites = toArray(sites);

现在我们有了路径,我们创造了水果和颜色的球。

var globs = [];
sites.forEach(function(data) {
    globs.push(data + '**/color*');
    globs.push(data + '**/fruit*');
});

使用当前配置,您将获得包含8个条目的数组。接下来,让我们定义concat-task。这就是你的意思"批量"在一起,我们需要一个所谓的流数组(我写了here)。它是现有阵列到许多gulp流的简单映射,它们通过event-stream模块在​​最后合并。随着颜色/水果的发生,我们需要通过我们的concat名称和目的地名称来创造一点点。 请注意,我使用changed插件来防止无用的构建。

gulp.task('concat', function() {
    var tasks = globs.map(function(glob) {
        var file = glob.indexOf('color') >= 0 ? 'col' : 'fru';
        var dest = glob.replace('**/color*','').replace('**/fruit*','') + 'web';
        return gulp.src(glob)
            .pipe(concat(file + '.txt'))
            .pipe(gulp.dest(dest))
    });

    return es.merge.apply(null, tasks);
});

此任务现在可以完成我们需要的所有工作,并逐步完成。所以我们的手表流程非常简单。

gulp.task('watch', ['concat'], function() {
    gulp.watch(globs, ['concat']);
});

希望这有帮助!

<强>更新

好吧,我做了一些调整,这可能会阻止整个项目的重建。

首先,我将concatStream解压缩到一个函数。这实际上是你用自己的样本做过的事情:

var concatStream = function(glob) {
    var file = glob.indexOf('color') >= 0 ? 'farbe' : 'frucht';
    var dest = glob.replace('**/color*','').replace('**/fruit*','') + 'web';
    return gulp.src(glob)
        .pipe(concat(file + '.txt'))
        .pipe(header(alertMessage))
        .pipe(notify())
        .pipe(gulp.dest(dest))
};

根据Glob(我们从目录中选择颜色或水果的文件模式),我们定义了一个新的输出(文件,当&#39; col&#39; col&#39;我们的搜索字符串,&#39; fru&#39;否则)和新目的地(只是没有颜色/水果搜索模式的旧文件夹)。 gulp.task(&#39; concat&#39;)现在执行以下操作:

gulp.task('concat', function() {
    var tasks = globs.map(concatStream);
    return es.merge.apply(null, tasks);
});

我们的每个globs(console.log,如果你想知道其中的内容)都被映射到concatStream,然后新的流数组被合并并执行。

手表任务现在是新的...我们的确和我们的&#39; concat&#39;任务:

gulp.task('watch', ['concat'], function() {
    globs.map(function(glob) {
        gulp.watch(glob, function() {
           return concatStream(glob);
        })
    })
});

对于每个glob,我们创建一个新的观察者,它再次调用concatStream。


更新

小改变

在glob内部,将通配符(*)更改为可选的单字符匹配(?),将允许我们对输出文件使用相同的名称(例如color和fruit)。

var globs = [];
    sites.forEach(function(data) {
        globs.push(data + '**/color?');
        globs.push(data + '**/fruit?');
    });

这也是......

var concatStream = function(glob) {
    var file = glob.indexOf('color') >= 0 ? 'color' : 'fruit';
    var dest = glob.replace('**/color?','').replace('**/fruit?','') + 'web';
    return gulp.src(glob)
        .pipe(concat(file + '.txt'))
        .pipe(header(alertMessage))
        .pipe(notify())
        .pipe(gulp.dest(dest))
};

现在我可以为输出文件保留颜色 fruit 的名称,而不必担心匹配名称并将其现有内容添加回文件