32

我想用 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);

这似乎更好,因为它更灵活,但是现在我的 gulpfile 充满了几个不必要的功能。

有没有更好的办法 ?

4

7 回答 7

29

您的第二次尝试走在了正确的轨道上,只需要使用一些DRY闭包

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));
于 2017-02-06T11:47:33.690 回答
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/'
}

希望有帮助。

于 2016-01-21T16:15:35.260 回答
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"));

随意删除标签的东西。

于 2020-09-16T15:14:23.550 回答
0

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

Gulp 无法处理任务中的参数。为了处理开发/生产构建,我们可以使用yargs和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,并且如果确实需要在一个构建中多次运行相同的任务,则确实不适合。它不适合,因为它根本不干燥。

例如,如果您需要为不同的站点部分生成多个 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 项目中处理此问题的方式。

于 2017-01-03T22:15:42.373 回答
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 文件。但我认为它更干净、更合乎逻辑,并且消除了 gulp 的一系列限制。

于 2018-04-06T09:31:40.347 回答
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']);  
于 2017-02-07T12:06:29.290 回答
-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 中执行简单的任务,例如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,那么这是我会采取的方向。

于 2016-02-03T14:42:52.780 回答