Можно ли передать флаг Gulp, чтобы он выполнял задачи по-разному?

369

Обычно в Gulp задачи выглядят так:

gulp.task('my-task', function() {
    return gulp.src(options.SCSS_SOURCE)
        .pipe(sass({style:'nested'}))
        .pipe(autoprefixer('last 10 version'))
        .pipe(concat('style.css'))
        .pipe(gulp.dest(options.SCSS_DEST));
});

Можно ли передать флаг командной строки в gulp (это не задача) и запустить ли он задачи условно на основании этого? Например

$ gulp my-task -a 1

А потом в моем gulpfile.js:

gulp.task('my-task', function() {
        if (a == 1) {
            var source = options.SCSS_SOURCE;
        } else {
            var source = options.OTHER_SOURCE;
        }
        return gulp.src(source)
            .pipe(sass({style:'nested'}))
            .pipe(autoprefixer('last 10 version'))
            .pipe(concat('style.css'))
            .pipe(gulp.dest(options.SCSS_DEST));
});
asolberg
источник
11
Поскольку он работает в узле, вы можете использовать его process.argvдля доступа к аргументам командной строки.
zzzzBov

Ответы:

528

Gulp не предлагает никакой утилиты для этого, но вы можете использовать один из многих парсеров командных аргументов. Мне нравится yargs. Должно быть:

var argv = require('yargs').argv;

gulp.task('my-task', function() {
    return gulp.src(argv.a == 1 ? options.SCSS_SOURCE : options.OTHER_SOURCE)
        .pipe(sass({style:'nested'}))
        .pipe(autoprefixer('last 10 version'))
        .pipe(concat('style.css'))
        .pipe(gulp.dest(options.SCSS_DEST));
});

Вы также можете комбинировать его с gulp-ifусловным потоком потока, что очень полезно для сборки dev и prod:

var argv = require('yargs').argv,
    gulpif = require('gulp-if'),
    rename = require('gulp-rename'),
    uglify = require('gulp-uglify');

gulp.task('my-js-task', function() {
  gulp.src('src/**/*.js')
    .pipe(concat('out.js'))
    .pipe(gulpif(argv.production, uglify()))
    .pipe(gulpif(argv.production, rename({suffix: '.min'})))
    .pipe(gulp.dest('dist/'));
});

И позвони с gulp my-js-taskили gulp my-js-task --production.

Кайо Кунья
источник
45
Это должно быть как-то упомянуто @ официальный Gulp GitHub, необходимые вещи!
Макс
2
Это видео объясняет, как этого добиться без яргов: youtube.com/watch?v=gRzCAyNrPV8
plankguy
9
Привет @plankguy, видео очень хорошее. Спасибо. Он показывает, как анализировать переменные окружения вручную, без какой-либо библиотеки. Небольшое отличие состоит в том, что видео посвящено переменным среды , в то время как в приведенном выше примере речь идет об аргументах командной строки , где Yargs - еще один инструмент, который помогает упростить потребление путем абстрагирования парсинга переменных.
Кайо Кунья
12
Если вы используете, npm run gulpто вы должны использовать его как npm run gulp -- --production.
ivkremer
3
Это упоминается в официальном gulp github (буквально).
Fracz
101

редактировать

gulp-utilявляется устаревшим и должен быть избегать, поэтому рекомендуется использовать minimist вместо, который gulp-utilуже используется.

Поэтому я изменил некоторые строки в моем gulpfile, чтобы удалить gulp-util:

var argv = require('minimist')(process.argv.slice(2));

gulp.task('styles', function() {
  return gulp.src(['src/styles/' + (argv.theme || 'main') + '.scss'])
    
});

оригинал

В моем проекте я использую следующий флаг:

gulp styles --theme literature

Gulp предлагает объект gulp.envдля этого. В новых версиях он устарел, поэтому для этого вы должны использовать gulp-util. Задачи выглядят так:

var util = require('gulp-util');

gulp.task('styles', function() {
  return gulp.src(['src/styles/' + (util.env.theme ? util.env.theme : 'main') + '.scss'])
    .pipe(compass({
        config_file: './config.rb',
        sass   : 'src/styles',
        css    : 'dist/styles',
        style  : 'expanded'

    }))
    .pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'ff 17', 'opera 12.1', 'ios 6', 'android 4'))
    .pipe(livereload(server))
    .pipe(gulp.dest('dist/styles'))
    .pipe(notify({ message: 'Styles task complete' }));
});

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

gulp watch --theme literature

И моя задача стилей также работает.

Чао Ральф

RWAM
источник
6
gulp.envустарела , как вы можете видеть по сообщению журнала консоли при его запуске. Они просят вас использовать свой собственный парсер и предлагают yargsили minimist.
Кайо Кунья
2
Спасибо @CaioToOn за подсказку. Я обновил свой ответ и мой проект тоже;)
RWAM
4
Вы можете сократить util.env.theme ? util.env.theme : 'main'до util.env.theme || 'main'. В любом случае +1.
Ренан
9
gulp-utilиспользует minimistбиблиотеку для разбора аргументов командной строки. Так что если вы используете gulp-util, вам не нужна дополнительная библиотека для этой цели. Документ: github.com/substack/minimist
Rockallite
57

Вот быстрый рецепт, который я нашел:

gulpfile.js

var gulp   = require('gulp');

// npm install gulp yargs gulp-if gulp-uglify
var args   = require('yargs').argv;
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');

var isProduction = args.env === 'production';

gulp.task('scripts', function() {
  return gulp.src('**/*.js')
    .pipe(gulpif(isProduction, uglify())) // only minify if production
    .pipe(gulp.dest('dist'));
});

CLI

gulp scripts --env production

Оригинал ссылки (больше не доступен): https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-params-from-cli.md

Альтернатива с минимистом

Из обновленной ссылки: https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-arguments-from-cli.md

gulpfile.js

// npm install --save-dev gulp gulp-if gulp-uglify minimist

var gulp = require('gulp');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');

var minimist = require('minimist');

var knownOptions = {
  string: 'env',
  default: { env: process.env.NODE_ENV || 'production' }
};

var options = minimist(process.argv.slice(2), knownOptions);

gulp.task('scripts', function() {
  return gulp.src('**/*.js')
    .pipe(gulpif(options.env === 'production', uglify())) // only minify if production
    .pipe(gulp.dest('dist'));
});

CLI

gulp scripts --env production
AEQ
источник
2
Эта ссылка на рецепт, похоже, исчезла. Есть еще один, который использует пакет minimist : pass-arguments-from-cli.md . Это имеет смысл, так как сам глоток использует минималист .
Yuvilio
39

Есть очень простой способ сделать on/offфлаги без разбора аргументов. gulpfile.jsэто просто файл, который выполняется как любой другой, так что вы можете сделать:

var flags = {
  production: false
};

gulp.task('production', function () {
  flags.production = true;
});

И использовать что-то вроде gulp-ifусловно выполнить шаг

gulp.task('build', function () {
  gulp.src('*.html')
    .pipe(gulp_if(flags.production, minify_html()))
    .pipe(gulp.dest('build/'));
});

Выполнение gulp buildдаст хороший HTML, а gulp production buildминимизирует его.

Эмиль Иванов
источник
2
Отличная идея, экономит с помощью yargs, я расширил это, имея задачу 'pre-production', которая устанавливает переменные, а затем 'production' имеет массив зависимостей ['build', 'pre-production']. Таким образом, вы можете просто запустить «производство глотка».
Киган 82
Ницца! Я использую это перед настройкой потока, сgulp.task('mytask', function() { if (flags.myflag ) { flaggedtask } else { unflaggedask } });
Генри
Я думаю, что это
отличный
@ Keegan'shairstyle82 Я сделал нечто подобное, но мне пришлось использовать последовательность выполнения, чтобы гарантировать отсутствие условий гонки при настройке свойств flags.
CalMlynarczyk
3
Недостаток этого метода заключается в том, что вам нужно изменять gulpfile.js каждый раз, когда вы хотите изменить переменные флага, а не просто передавать аргументы команде gulp в терминале.
Jbyrd
33

Если у вас есть строгие (упорядоченные!) Аргументы, вы можете получить их, просто проверив process.argv.

var args = process.argv.slice(2);

if (args[0] === "--env" && args[1] === "production");

Выполните это: gulp --env production

... однако я думаю, что это слишком строго и не пуленепробиваемо! Итак, я немного поиграл ... и в итоге получил следующую полезную функцию:

function getArg(key) {
  var index = process.argv.indexOf(key);
  var next = process.argv[index + 1];
  return (index < 0) ? null : (!next || next[0] === "-") ? true : next;
}

Он ест имя аргумента и будет искать его в process.argv. Если ничего не было найдено, оно выплевывает null. В противном случае, если их нет в качестве следующего аргумента или следующий аргумент является командой, а не значение (мы отличаемся штрихом), trueвозвращается. (Это потому, что ключ существует, но там просто нет значения). Если все предыдущие случаи потерпят неудачу, мы получим следующее значение аргумента.

> gulp watch --foo --bar 1337 -boom "Foo isn't equal to bar."

getArg("--foo") // => true
getArg("--bar") // => "1337"
getArg("-boom") // => "Foo isn't equal to bar."
getArg("--404") // => null

Хорошо, пока достаточно ... Вот простой пример использования gulp :

var gulp = require("gulp");
var sass = require("gulp-sass");
var rename = require("gulp-rename");

var env = getArg("--env");

gulp.task("styles", function () {
  return gulp.src("./index.scss")
  .pipe(sass({
    style: env === "production" ? "compressed" : "nested"
  }))
  .pipe(rename({
    extname: env === "production" ? ".min.css" : ".css"
  }))
  .pipe(gulp.dest("./build"));
});

Запустить его gulp --env production

yckart
источник
имя аргумента должно начинаться с дефиса (ов): if (args[0] === '--env' && args[1] === 'production');по крайней мере в
gulp
@yckart - вам, вероятно, следует добавить require ('..') для getArg в вашем примере кода.
Jbyrd
7

Я построил плагин для ввода параметров из командной строки в обратный вызов задачи.

gulp.task('mytask', function (production) {
  console.log(production); // => true
});

// gulp mytask --production

https://github.com/stoeffel/gulp-param

Если кто-то обнаружит ошибку или улучшит ее, я буду счастлив объединить PR.

stoeffel
источник
4

И если вы используете typcript ( gulpfile.ts), сделайте это для yargs(основываясь на превосходном ответе @Caio Cunha https://stackoverflow.com/a/23038290/1019307 и других комментариях выше):

устанавливать

npm install --save-dev yargs

typings install dt~yargs --global --save

.ts файлы

Добавьте это к .ts файлам:

import { argv } from 'yargs';

...

  let debug: boolean = argv.debug;

Это должно быть сделано в каждом файле .ts индивидуально (даже tools/tasks/projectфайлы, которые импортированы в gulpfile.ts/js).

Запустить

gulp build.dev --debug

Или при npmпрохождении арг через глоток:

npm run build.dev -- --debug
HankCa
источник
2

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

// npm install --save-dev gulp gulp-if gulp-uglify minimist

var gulp = require('gulp');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');

var minimist = require('minimist');

var knownOptions = {
  string: 'env',
  default: { env: process.env.NODE_ENV || 'production' }
};

var options = minimist(process.argv.slice(2), knownOptions);

gulp.task('scripts', function() {
  return gulp.src('**/*.js')
    .pipe(gulpif(options.env === 'production', uglify())) // only minify in production
    .pipe(gulp.dest('dist'));
});

Затем выполните глоток с:

$ gulp scripts --env development

Источник

HaNdTriX
источник
2
var isProduction = (process.argv.indexOf("production")>-1);

CLI gulp productionвызывает мою производственную задачу и устанавливает флаг для любых условий.

Киган 82
источник
1

Мы хотели передать другой файл конфигурации для разных сред - один для производства , разработки и тестирования . Это код в файле gulp:

//passing in flag to gulp to set environment
//var env = gutil.env.env;

if (typeof gutil.env.env === 'string') {
  process.env.NODE_ENV = gutil.env.env;
}

Это код в файле app.js:

  if(env === 'testing'){
      var Config = require('./config.testing.js');
      var Api = require('./api/testing.js')(Config.web);
    }
    else if(env === 'dev'){
       Config = require('./config.dev.js');
        Api = require('./api/dev.js').Api;
    }
    else{
       Config = require('./config.production.js');
       Api = require('./api/production.js')(Config.web);
    }

А потом запустить его глотком --env=testing

Сара Инес Кальдерон
источник
1

Прошло некоторое время с тех пор, как этот вопрос был опубликован, но, возможно, это кому-нибудь поможет.

Я использую GULP CLI 2.0.1 (установлен глобально) и GULP 4.0.0 (установлен локально), вот как вы делаете это без каких-либо дополнительных плагинов. Я думаю, что код довольно понятен.

var cp = require('child_process'), 
{ src, dest, series, parallel, watch } = require('gulp');

// == availableTasks: log available tasks to console
function availableTasks(done) {
  var command = 'gulp --tasks-simple';
  if (process.argv.indexOf('--verbose') > -1) {
    command = 'gulp --tasks';
  }
  cp.exec(command, function(err, stdout, stderr) {
    done(console.log('Available tasks are:\n' + stdout));
  });
}
availableTasks.displayName = 'tasks';
availableTasks.description = 'Log available tasks to console as plain text list.';
availableTasks.flags = {
  '--verbose': 'Display tasks dependency tree instead of plain text list.'
};
exports.availableTasks = availableTasks;

И запустить из консоли:

gulp availableTasks

Затем бегите и посмотрите на различия:

gulp availableTasks --verbose
TMMC
источник