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

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

问题描述

我编写了一个 gulp 文件,它监视多个目录的更改,然后创建与多个指定目标的连接.

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

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

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

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

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

--内部/|-- 颜色1|-- 颜色2|-- 水果1|-- 水果2-- 外/|-- 颜色1|-- 颜色2|-- 水果1|-- 水果2-- 网络/|-- 颜色.txt|-- 水果.txt

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

<代码>{网站":{一": {"a": "/path/to/one/a/","b": "/path/to/one/b/"},二": {"a": "/path/to/two/a/","b": "/path/to/two/b/"}}}

最后是 gulpfile.js

//包含本地 Gulpvar 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 web = "web/";//杂项var alertMessage = "# 生成的文件 - 不要修改

";//总共 8 个用于连接的任务//连接到 colors.txt - 4 个任务//颜色任务 1: [ Site =>一] [分支=>一个 ]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());});//颜色任务 2: [ Site =>一] [分支=>乙]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());});//颜色任务 3: [ Site =>二] [分支=>一个 ]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());});//颜色任务 4: [ Site =>二] [分支=>乙]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());});//连接到 fruits.txt - 4 个任务//水果任务 1: [ Site =>一] [分支=>一个 ]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());});//水果任务 2: [ Site =>一] [分支=>乙]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());});//水果任务 3: [ Site =>二] [分支=>一个 ]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());});//水果任务 4: [ Site =>二] [分支=>乙]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());});//监视指定 {directories}/{files} 中的所有事件,然后触发相应的任务//总共 8 个监视作业gulp.task("watch", function () {//颜色相关的手表作业 - 共 4 个//彩色手表 1: [ Site =>一] [分支=>一个 ]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");});//彩色手表 2: [ Site =>一] [分支=>乙]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");});//颜色表 3: [ Site =>二] [分支=>一个 ]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 =>二] [分支=>乙]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: [ Site =>一] [分支=>一个 ]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: [ Site =>一] [分支=>乙]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 =>二] [分支=>一个 ]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 =>二] [分支=>乙]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("背景",[one_a_color"、one_b_color"、two_a_color"、two_b_color"、one_a_fruit"、one_b_fruit"、two_a_fruit"、two_b_fruit"、手表"]);

上面的 gulp 文件可以正常工作.但是,如您所见,大部分代码都是重复的,只有 gulp.src 和 gulp.dest 以及任务名称发生了变化.

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

解决方案

不是那么容易的任务,但让我们看看我们是否可以优化它.Gulp 和 Globs 大量处理数组,这就是为什么我们必须先将路径转换为数组:

var gulp = require('gulp');var concat = require('gulp-concat');var es = require('事件流');var sites = require('./config.json').sites;var toArray = function(conf) {var arr = [];for(conf 中的 var 键){if(typeof conf[key] === 'object') {arr = arr.concat(toArray(conf[key]));} 别的 {arr.push(conf[key]);}}返回 arr;};var 站点 = toArray(站点);

现在我们有了路径,我们为水果和颜色创建球.

var globs = [];站点.forEach(函数(数据){globs.push(data + '**/color*');globs.push(data + '**/fruit*');});

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

gulp.task('concat', function() {var 任务 = globs.map(function(glob) {var file = glob.indexOf('color') >= 0 ?'col' : 'fru';var dest = glob.replace('**/color*','').replace('**/fruit*','') + 'web';返回 gulp.src(glob).pipe(concat(文件 + '.txt')).pipe(gulp.dest(dest))});返回 es.merge.apply(null, 任务);});

这个任务现在完成了我们需要的一切,而且是渐进式的.所以我们的观察过程相当简单.

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

希望这会有所帮助!

更新

好的,我做了一些调整,应该可以防止你的整个项目被重建.

首先,我将 concatStream 提取到一个函数中.这实际上是您对自己的样本所做的一件事:

var concatStream = function(glob) {var file = glob.indexOf('color') >= 0 ?'farbe' : '水果';var dest = glob.replace('**/color*','').replace('**/fruit*','') + 'web';返回 gulp.src(glob).pipe(concat(文件 + '.txt')).pipe(标头(alertMessage)).pipe(通知()).pipe(gulp.dest(dest))};

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

gulp.task('concat', function() {var 任务 = globs.map(concatStream);返回 es.merge.apply(null, 任务);});

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

watch 任务现在是新的......我们做的有点像我们的concat"任务:

gulp.task('watch', ['concat'], function() {globs.map(函数(glob){gulp.watch(glob,函数(){返回连接流(glob);})})});

对于每个 glob,我们创建一个新的 watcher,它只是再次调用 concatStream.

<小时>

更新

小改动

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

var globs = [];站点.forEach(函数(数据){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';返回 gulp.src(glob).pipe(concat(文件 + '.txt')).pipe(标头(alertMessage)).pipe(通知()).pipe(gulp.dest(dest))};

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

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

";

// 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

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

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