Задача Gulp с другим источником в зависимости от аргументов

Я хочу сделать что-то простое, используя 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 или что-то в этом роде? В следующем примере я притворяюсь, что могу передать путь как аргумент

Итак, я пробую что-то подобное, используя 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."

Это, очевидно, менее удобно в сопровождении, поскольку мы вызываем все больше и больше задач gulp изнутри задачи dev 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 замусорен несколькими ненужными функциями.

Есть ли способ лучше ?


person jth41    schedule 01.09.2015    source источник
comment
не очень хорошо знаком с gulp, но пробовали ли вы вызывать moveViews() и moveJs() из самого move()?   -  person joyBlanks    schedule 01.09.2015
comment
Я не понимаю, почему вы делаете это через gulp вместо использования mv или cp???   -  person Mathletics    schedule 01.09.2015
comment
Это заслуживает большего внимания, какой отличный вопрос - нашли ли вы с тех пор работоспособное решение для этого? Я просто сталкиваюсь с этим.   -  person Dan Kanze    schedule 29.04.2016
comment
@DanKanze Мне тоже было бы интересно узнать ваше мнение о моем свежем ответе ниже.   -  person Wtower    schedule 04.01.2017
comment
Вы всегда знаете пути для dev и prod? Если это так, просто создайте переменную destination в самой верхней области вашего gulpfile и установите ее из task.   -  person Mudlabs    schedule 05.11.2020


Ответы (7)


Вы были на правильном пути со второй попытки, просто нужно было использовать немного 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));
person Dennis Baizulin    schedule 06.02.2017
comment
Используя gulp 4, мне пришлось использовать эту сигнатуру задачи gulp.task('dev', () => { return createTransformTaskClosure(config.output_development) }); - person SliverNinja - MSFT; 11.12.2017

Я сделал что-то подобное, используя одну функцию:

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

Надеюсь, это поможет.

person MaxRocket    schedule 21.01.2016

Для начала, для протокола, соответствующая проблема github gulp#1225.

Gulp не может обрабатывать параметры в задачах. Для обработки сборки dev/production мы можем использовать 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);

Таким образом, по сути, мы отделяем метод задачи от задачи глотка, за счет необходимости указывать «подключение» метода задачи к новой функции, которая использует определенную конфигурацию пути. Но это имеет то преимущество, что всякий раз, когда вам нужно внести изменение в метод задачи, оно находится в одном месте. Также вы можете легко увидеть, какая часть сайта использует какие методы.

Точно так же я решаю эту проблему в моем проекте gulpfile.

person Wtower    schedule 03.01.2017
comment
Отвратительно минусовать без должного объяснения. - person Wtower; 03.02.2017

Как насчет чего-то вроде следующего:

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']);  
person ordepim    schedule 07.02.2017

Немного опоздал на вечеринку. У меня похожая проблема, я не смог найти простого решения, поэтому я придумал этот подход, чтобы использовать комбинацию 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.

person Xun Yang    schedule 06.04.2018

Помогает ли это?

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

Не стесняйтесь удалять этикетку.

person unsocialcattle    schedule 16.09.2020

Не уверен, что это полезно, но просто мои несколько пенсов на идею: -

Имейте следующее в файле 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 dev или gulp 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, то это направление, которое я бы выбрал.

person Adam Martin    schedule 03.02.2016