根据参数使用不同来源的Gulp任务

时间:2015-09-01 01:14:29

标签: javascript gulp dry yargs

我想用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文件中充斥着几个不必要的函数。

有更好的方法吗?

7 个答案:

答案 0 :(得分:27)

第二次尝试时你走在正确的轨道上,只需要使用一点DRYclosures

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

答案 1 :(得分:1)

我使用单一功能做了类似的事情:

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

希望有所帮助。

答案 2 :(得分:0)

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

Gulp无法处理任务中的参数。为了处理开发/生产构建,我们可以使用yargsgulp-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 mytask --production运行gulp,并且如果确实需要在一个构建中多次运行相同的任务,则不适合。它不合适,因为它根本不是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任务分开,并且必须为使用特定路径配置的新函数指定任务方法的“连接”成本。但这样做的好处是,无论何时需要对任务方法进行更改,它都在一个地方。您还可以轻松查看网站的哪个部分使用哪种方法。

这也是我在gulpfile project中处理此问题的方法。

答案 3 :(得分:0)

如下所示:

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

答案 4 :(得分:0)

派对有点晚了。我有类似的问题,找不到简单的解决方案,所以我想出了这种方法来使用npm和gulp的组合。

说你的gulpfile是:

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文件。但我认为它更清洁,更符合逻辑,并消除了一大堆限制。

答案 5 :(得分:0)

有帮助吗?

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

请随时删除标签内容。

答案 6 :(得分:-1)

不确定这是否有用,但只是我的几个便士的想法: -

在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 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,那么这就是我要采取的方向。