如何分批类似的吞咽任务以减少代码重复 [英] How to batch similar gulp tasks to reduce code repetition

查看:105
本文介绍了如何分批类似的吞咽任务以减少代码重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个gulp文件,用于监视多个目录中的更改,然后创建连接到多个指定的目标。



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



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



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

在每个分支中,有三个文件夹:
inner / outer / web /



我的任务是从内部和外部文件夹中获取类似的零件文件,并将它们连接到相关的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

  //包含本地Gulp 
var gulp = require(gulp) ;

//从config.json获取数据
var sites = require(./ config.json)。sites;

//包含特定于Gulp的插件
var gConcat = require(gulp-concat);
var gHeader = require(gulp-header);
var gUtil = require(gulp-util);
var gNotify = require(gulp-notify);

//安装目录
var outer =outer /;
var inner =inner /;
var web =web /;

// Misc
var alertMessage =#生成文件 - 不要修改\\\
\\\
;

// 8个连接的总任务

//连接到colors.txt - 4个任务
//颜色任务1:[Site =>一个] [Branch => a]
gulp.task(one_a_color,function(){
return gulp.src([sites.one.a + outer +color?,sites.one.a + inner +颜色?))
.pipe(gConcat(colors.txt))
.pipe(gHeader(alertMessage))
.pipe(gulp.dest(sites.one.a + web))
.pipe(gNotify());
});

//颜色任务2:[网站=>一个] [Branch => b]
gulp.task(one_b_color,function(){
return gulp.src([sites.one.b + outer +color?,sites.one.b + inner +颜色?))
.pipe(gConcat(colors.txt))
.pipe(gHeader(alertMessage))
.pipe(gulp.dest(sites.one.b + web))
.pipe(gNotify());
});

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

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

//连接到fruits.txt - 4个任务
//水果任务1:[Site =>一个] [Branch => a]
gulp.task(one_a_fruit,function(){
return gulp.src([sites.one.a + outer +fruit?,sites.one.a + inner +水果?))
.pipe(gConcat(fruits.txt))
.pipe(gHeader(alertMessage))
.pipe(gulp.dest(sites.one.a + web))
.pipe(gNotify());
});

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

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

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

//观察指定{目录} / {文件}中的所有事件,然后触发适当的任务
// 8共计监视作业
gulp.task(watch,功能(){
//颜色相关的手表作业 - 总计4
//彩色手表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);
});

//彩色手表4:[Site =>两个] [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);
});

//水果相关手表作业 - 总计4
//水果手表1:[网站=>一个] [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);
});

//水果手表2:[网站=>一个] [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);
});

//水果表3:[Site =>两个] [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);
});

//水果手表4:[Site =>两个] [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);
});
});

//运行所有任务
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文件,所以不必为每个任务重复代码,而是可以将相似的任务组合在一起。

解决方案

不是那么容易的任务,但让我们看看我们是否可以优化它。 Gulp和Globs很大程度上处理数组,因此我们必须首先将路径转换为数组:

  var gulp = require '吞'); 
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。下面是你的意思是批处理在一起,我们需要一个所谓的流数组(我写了关于这里)。它是将现有数组简单映射到许多gulp流,它们通过 event-stream 模块在末尾合并。随着颜色/水果事情的发展,我们需要对concat名称和目标名称进行一点创意。
请注意,我使用已更改插件来防止无用的构建。

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

返回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(文件模式,我们从我们的目录中选择颜色或水果),我们定义一个新的输出(文件,当'color'在我们的搜索字符串中时'col',否则'fru')和一个新的目的地(这只是没有颜色/水果搜索模式的旧文件夹)。
gulp.task('concat')现在具有以下功能:

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

我们的每个globs(console.log,如果你想知道里面有什么)被映射到concatStream,然后新的数组流被合并并执行。



手表任务现在是新的......我们的操作与我们的'concat'任务:

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

对于每个glob,我们创建一个新的监视器,它只是再次调用concatStream。






更新

小变化



在glob中,将通配符(*)更改为可选的单个字符匹配(?),将允许我们为输出文件(例如颜色和水果)使用相同的名称。

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

这也是......

  var concatStream = function(glob){
var file = glob.indexOf('color')> = 0? '颜色':'水果';
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))
};

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


I have written a gulp file that watches over several directories for changes, and then create concatenation to multiple specified destination.

Here is a simplified version of my project structure:

I have 2 site folders: one/ and two/

Each site have two branch folders: a/ and b/

Inside each branch, there are three folders: inner/, outer/ and web/

My task is to grab similar part files from the inner and outer folders, and concatenate them into relative web folders. Below is a simple example of desired output.

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

I have created a config.json file to hold site specific configuration. Currently only using it to customize site paths. Here is the 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/"
    }
  }
}

And finally here is the 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"
    ]
);

The above gulp file works and does the job. However, as you can see, most of the codes are repeated, only part that changes are the gulp.src and gulp.dest, along with the task names.

My question is. Would it be possible to simplify this gulp file, so instead of repeating codes for every tasks, maybe similar tasks can be batched together.

解决方案

Not that easy a task, but let's see if we can optimise that. Gulp and Globs greatly deal with arrays, that's why we have to convert your paths to an array first:

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

Now that we have the paths, we create the globs for fruits and colors.

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

With your current config, you get an array of 8 entries. Next, let us define the concat-task. Here is what you mean with "batched" together, we need a so called stream array (I wrote about that here). It's a simple mapping of an existing array to many gulp streams, which are merged at the end via the event-stream module. With the color/fruit thing going on, we need to be a little creative with our concat names and dest names. Note that I use the changed plugin to prevent useless builds.

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);
});

This task now does everything we need, and incrementally so. So our watch process is rather straightforward.

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

Hope this helps!

Update

Alright, I made some adaptations, which should prevent having your whole project rebuilt.

First, I extracted the concatStream to a function. This is actually the one thing you already did with your own sample:

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))
};

Depending on the Glob (the file pattern we select either colors or fruits from our directories), we define a new output (file, is 'col' when 'color' is in our search string, 'fru' otherwise) and a new destination (which is just the old folder without the colors/fruits search pattern). gulp.task('concat') does now the following:

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

Each of our globs (console.log them, if you want to know what's in there) gets mapped to the concatStream, then the new array of streams gets merged and executed.

The watch task is now new... we do kinda the same as with our 'concat' task:

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

For each glob, we create a new watcher, which just calls the concatStream again.


Update

Small change

Inside glob, changing the wildcard (*) to an optional single character match (?), will allow us to use the same name for output file (ex. color and fruit).

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

And this as well...

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))
};

Now I can keep the names of color and fruit for my output file, without worrying bout glob matching the name and adding its existing content back onto the file

这篇关于如何分批类似的吞咽任务以减少代码重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆