Gulp 具有不同来源的任务取决于参数

Gulp task with different source depending on arguments

我想使用 gulp 完成一些简单的事情。我想编写一个通用方法将文件从特定源目录移动到输出目录。

假装我们有这样的东西

var args = require('yargs');
function transform-move-jsx-Development() 
{
  gulp.src(config.sourceJSX)
  .pipe(react, browserify, etc....)
  .pipe(gulp.dest(config.output_development));
};

function transform-move-jsx-Production() 
{
  gulp.src(config.sourceJSX)
  .pipe(react, browserify, etc....)
  .pipe(gulp.dest(config.output_production));
};

gulp.task('transform-move-jsx-Development', transform-move-jsx-Development);
gulp.task('transform-move-jsx-Production', transform-move-jsx-Production);

gulp.task('prod', [transform-move-jsx-Production]);
gulp.task('dev', ['transform-move-jsx-Development']);

这两个任务:transform-move-jsx-Production 和 transform-move-jsx-Development 除了输出目录不同外其他都是一样的。我想让它更干(不要重复自己)。我应该能够制作一个可以使用 yarg 参数或其他东西的方法吗?在下一个示例中,我假装我可以将路径作为 arg

所以我使用 yargs 尝试这样的事情

var args = require('yargs');

function transform-move-jsx() 
{ 
    return gulp.src(config.sourceJSX)
    .pipe(gulp.dest(args.outputDirectory));
};

gulp.task('dev', ['transform-move-jsx']);

然而,这现在要求我在命令行 gulp 调用中添加参数

gulp dev --"path to output, etc."

随着我们从 dev gulp 任务内部调用越来越多的 gulp 任务,这显然难以维护。无论如何都会很混乱,因为我们不需要知道实现细节,比如当我们 运行 gulp dev

时输出目录结构是什么

我可以改为这样做:

function transform-move-jsx(destination) 
{ 
    return gulp.src(config.sourceJSX)
    .pipe(gulp.dest(destination));
};

function transform-move-jsx-Development() 
{
    transform-move-jsx("./output/development/");
};

function transform-move-jsx-Production() 
{
    transform-move-jsx("./output/production/");
};

gulp.task('transform-move-jsx-Development',transform-move-jsx-Development);
gulp.task('transform-move-jsx-Production', transform-move-jsx-Production);

gulp.task('prod',  transform-move-jsx-Production);
gulp.task('dev',  transform-move-jsx-Development);

这似乎更好,因为它更灵活,但是现在我的 gulp 文件中充斥着一些不必要的函数。

有没有更好的方法?

我用一个函数做了类似的事情:

function getDest(folder){
    var folder = folder || '';
    var newDest;
    if (args.build){
        newDest = config.build.home + folder;
    }
    if (args.temp){
        newDest = config.temp.home + folder;
    }
    return newDest;
}

然后,当我调用 gulp.dest():

.pipe(gulp.dest(getDest())) // defaults to ./ directory

或者如果我想要一个子文件夹:

.pipe(gulp.dest(getDest(config.css)))

我的配置文件只有路径,即:

config = {
   css: '/css/',
   home: './',
   js: '/js/'
}

希望对您有所帮助。

不确定这是否有用,但只是我的一点想法:-

在 gulp 文件中包含以下内容。

var args = require('yargs'),
    config = require('./config.js'),
    run = require('gulp-sequence');

gulp.task('transform-move-jsx-all', function() {
    return gulp.src(config.sourceJSX)
        .pipe(react, browserify, etc....)
        .pipe(gulp.dest(config.current.output));
};

gulp.task('prod', function(done) {
    config.current = config.prod;
    run( 'transform-move-jsx' /* and any additional sequential tasks here*/)(done);
});

gulp.task('dev', function(done) {
    config.current = config.dev;
    run( 'transform-move-jsx' /* and any additional sequential tasks here*/)(done);
});

这样您就可以在 gulp 中完成简单的任务,例如 gulp devgulp prod

它需要一个类似于下面的 config.js 文件:

var config = {
    current : {
        // Will set when running each task
    },
    /* Keep dev and prod adhering to the same structure/model so that they are interchangable */
    dev : {
        output : 'dev_output',
    },
    prod : {
        output : 'prod_output'
    },
    sourceJSX : [ 'file1.jsx' ],
    etc...
}

使用 yargs 可能有更简洁的方法,但如果你只是想要一个干净的 gulp + task 那么我会选择这个方向。

首先,为了记录,相关的 github 问题 gulp#1225

Gulp 无法处理任务中的参数。为了处理 dev/production 构建,我们可以使用 yargs and gulp-if:

var gulp = require('gulp');
var argv = require('yargs').argv;
var gulpif = require('gulp-if');
var production = argv.production;

然后,例如,在 CSS 任务中:

return gulp.src(paths.css)
  .pipe(gulpif(!production, sourcemaps.init()))
  .on('error', handleError('CSS'))
  .pipe(concat('style.min.css'))
  .pipe(gulpif(production, autoprefixer(config.autoprefixer_versions)))
  .pipe(gulpif(production, minifyCSS()))
  .pipe(sourcemaps.write())
  .pipe(gulp.dest(paths.build + 'css/'));

如您所见,使用 gulp-if 可以正确处理管道。

但是上面仍然需要运行 gulp和gulp mytask --production,如果确实同一个任务需要在一次构建中多次运行,那么真的不合适.不适合,因为它根本不是DRY。

例如,如果您需要为不同的站点部分生成多个 CSS 版本,则必须重复上述任务 n 次。但是由于 gulp 无法处理参数,我们需要做一些类似的事情:

var taskMethods = {
  css: function (paths) {
    return gulp.src(paths.css)
      .pipe(gulpif(!production, sourcemaps.init()))
      .on('error', handleError('CSS'))
      .pipe(concat('style.min.css'))
      .pipe(gulpif(production, autoprefixer(config.autoprefixer_versions)))
      .pipe(gulpif(production, minifyCSS()))
      .pipe(sourcemaps.write())
      .pipe(gulp.dest(paths.build + 'css/'));
  }
};

var pathsIndex = {
  css: [...],
  build: '...'
};

var tasksIndex = {
  css: function() { return taskMethods(pathsIndex); }
}

var pathsAdmin = {...};
var tasksAdmin = {...};

gulp.task('cssIndex', tasksIndex.css);
gulp.task('cssAdmin', tasksAdmin.css);

所以本质上我们将任务方法与 gulp 任务分开,代价是必须将任务方法的 'wire-up' 指定给使用特定路径配置的新函数。但这样做的好处是,无论何时您需要对任务方法进行更改,它都在一个地方。您还可以轻松查看站点的哪个部分使用了哪些方法。

这也是我在gulpfile project.

中处​​理这个问题的方式

您第二次尝试的方向是正确的,只需要利用一点 DRY and closures

function createTransformTaskClosure (destination) {
    return function () {
        return gulp.src(config.sourceJSX)
                   .pipe(gulp.dest(destination));
    };
}

gulp.task('dev', createTransformTaskClosure(config.output_development));
gulp.task('prod', createTransformTaskClosure(config.output_production));

像下面这样的东西怎么样:

var args = require('yargs');
function transform-move-jsx(destination) {
    return function(){
        return gulp.src(config.sourceJSX)
                   .pipe(react, browserify, etc....)
                   .pipe(gulp.dest(destination));
    }
};

gulp.task('transform-move-jsx-Development', transform-move-jsx(config.output_development));
gulp.task('transform-move-jsx-Production', transform-move-jsx(config.output_production));

gulp.task('prod', [transform-move-jsx-Production]);
gulp.task('dev', ['transform-move-jsx-Development']);  

聚会有点晚了。我有一个类似的问题,找不到简单的解决方案,所以我想出了这种结合使用 npm 和 gulp.

的方法

假设您的 gulp 文件是:

var args = require('yargs');

function transform-move-jsx() 
{ 
    return gulp.src(config.sourceJSX)
    .pipe(gulp.dest(args.outputDirectory));
};

还有你的 npm 文件:

{
  ...
  "scripts": {
    "dev" : "gulp transform-moove-jsx --./output/development/ && gulp one && gulp two",
    "prod" : "gulp transform-moove-jsx --./output/production/  && gulp one && gulp two",
  }
}

此方法要求您已经在您的设置中使用 npm,依赖于系统并且运行效率较低并可能产生副作用,因为每个 npm 任务都会多次运行 gulp 文件。但我认为它更清晰、更合乎逻辑,并消除了 gulp.

的一系列限制

这有帮助吗?

const { src, dest, series } = require('gulp');

function moveJSX(dest = "./output/development/", label = "dev") {

  const source = config.sourceJSX;

  function task() { return src(source).pipe(dest(dest)); };

  task.displayName = `moveJSX:${label}`;
  
  return task;
}

// usage
series(moveJSX(), moveJSX("./output/production/", "prod"));

随意删除标签。