¿Es posible pasar una bandera a Gulp para que ejecute tareas de diferentes maneras?


369

Normalmente en Gulp las tareas se ven así:

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

¿Es posible pasar un indicador de línea de comando para tragar (eso no es una tarea) y hacer que ejecute tareas condicionalmente en función de eso? Por ejemplo

$ gulp my-task -a 1

Y luego en mi 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));
});

11
Como se está ejecutando en el nodo, probablemente podría usar process.argvpara acceder a los argumentos de la línea de comandos.
— zzzzBov

Respuestas:


528

Gulp no ofrece ningún tipo de utilidad para eso, pero puede usar uno de los muchos analizadores de argumentos de comando. Me gusta yargs. Debiera ser:

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

También puede combinarlo gulp-ifpara canalizar condicionalmente la transmisión, muy útil para la creación de desarrollo frente a producción:

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

Y llama con gulp my-js-tasko gulp my-js-task --production.


45
Esto debería mencionarse de alguna manera @ el gulp oficial gulp, ¡cosas esenciales!
— Max

2
Este video explica cómo lograr esto sin hilos: youtube.com/watch?v=gRzCAyNrPV8
— plankguy

99
Hola @plankguy, el video es muy bueno. Gracias. Muestra cómo analizar las variables de entorno a mano, sin ninguna lib. Una pequeña diferencia es que el video trata sobre variables de entorno , mientras que el ejemplo anterior trata sobre argumentos de línea de comandos , donde Yargs es otra herramienta que ayuda a simplificar el consumo al abstraer el análisis de variables.
— Caio Cunha

12
Si lo usa, npm run gulpentonces debe usarlo como npm run gulp -- --production.
— ivkremer

3
Esto se menciona @ the gulp github oficial (literalmente).
— fracz

101

Editar

gulp-utilestá en desuso y debe evitarse, por lo que se recomienda usar minimist en su lugar, que gulp-utilya se usó.

Así que he cambiado algunas líneas en mi archivo para eliminar gulp-util:

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

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

Original

En mi proyecto uso la siguiente bandera:

gulp styles --theme literature

Gulp ofrece un objeto gulp.envpara eso. Está en desuso en las versiones más recientes, por lo que debe usar gulp-util para eso. Las tareas se ven así:

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

La configuración del entorno está disponible durante todas las subtareas. Así que también puedo usar esta bandera en la tarea de observación:

gulp watch --theme literature

Y mi tarea de estilos también funciona.

Ciao Ralf


66
gulp.envestá en desuso , como puede ver en el mensaje de registro de la consola al ejecutarlo. Te piden que uses tu propio analizador y te sugieran yargso minimist.
— Caio Cunha

2
Gracias @CaioToOn por tu pista. He actualizado mi respuesta y mi proyecto también;)
— RWAM

44
Puedes acortar util.env.theme ? util.env.theme : 'main'a util.env.theme || 'main'. De todos modos +1.
— Renan

99
gulp-utilutiliza la minimistbiblioteca para el análisis de argumentos de línea de comando. Entonces, si está utilizando gulp-util, no necesita una biblioteca adicional para ese propósito. Documento: github.com/substack/minimist
— Rockallite

57

Aquí hay una receta rápida que encontré:

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

Referencia original (ya no está disponible): https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-params-from-cli.md

Alternativa con minimista

De Ref actualizado: 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

2
Ese enlace de receta parece desaparecido ahora. Hay otro que usa el paquete minimist en su lugar: pass-arguments-from-cli.md . Eso tiene sentido ya que el trago en sí usa minimist .
— yuvilio

39

Hay una manera muy simple de hacer on/offbanderas sin analizar los argumentos. gulpfile.jses solo un archivo que se ejecuta como cualquier otro, por lo que puede hacer:

var flags = {
  production: false
};

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

Y use algo como gulp-ifejecutar condicionalmente un paso

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

La ejecución gulp buildproducirá un buen html, mientras que gulp production buildlo minimizará.


2
Gran idea, ahorra usando hilos, he extendido esto al tener una tarea de 'preproducción' que establece los vars y luego 'producción' tiene una matriz de dependencia de ['construir', 'preproducción']. De esa manera, puede ejecutar 'producción de tragos'.
— Keegan 82

¡Agradable! Estoy usando esto antes de configurar la transmisión, congulp.task('mytask', function() { if (flags.myflag ) { flaggedtask } else { unflaggedask } });
— henry

Creo que esta es la mejor manera de hacerlo
— gztomas el

@ Keegan'shairstyle82 Hice algo similar pero tuve que utilizar la secuencia de ejecución para asegurarme de que no había condiciones de carrera al establecer las propiedades de flags.
— CalMlynarczyk

3
La desventaja de este método es que debe cambiar gulpfile.js cada vez que desee cambiar las variables de marca, en lugar de simplemente pasar argumentos al comando gulp en el terminal.
— jbyrd

33

Si tiene algunos argumentos estrictos (¡ordenados!), Puede obtenerlos simplemente marcando process.argv.

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

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

Ejecutalo: gulp --env production

... sin embargo, creo que esto es demasiado estricto y no a prueba de balas. Entonces, jugueteé un poco ... y terminé con esta función de utilidad:

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

Come un nombre de argumento y buscará esto en process.argv. Si no se encuentra nada, se escupe null. De lo contrario, si no hay un siguiente argumento o si el siguiente argumento es un comando y no truese devuelve un valor (diferimos con un guión) . (Eso es porque la clave existe, pero simplemente no hay valor). Si todos los casos anteriores fallarán, el siguiente argumento-valor es lo que obtenemos.

> 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

Ok, suficiente por ahora ... Aquí hay un ejemplo simple usando 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"));
});

Ejecutarlo gulp --env production


el nombre del argumento debe tener el prefijo guión (es):, if (args[0] === '--env' && args[1] === 'production');al menos en el trago 3.8.11
— piotr_cz

@yckart: probablemente debería agregar el require ('..') para getArg en su ejemplo de código.
— jbyrd

7

Construí un complemento para inyectar parámetros desde la línea de comandos en la devolución de llamada de la tarea.

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

// gulp mytask --production

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

Si alguien encuentra un error o lo mejora, me complace fusionar los RP.


4

Y si está utilizando typecript ( gulpfile.ts), haga esto para yargs(basándose en la excelente respuesta de @Caio Cunha https://stackoverflow.com/a/23038290/1019307 y otros comentarios anteriores):

Instalar en pc

npm install --save-dev yargs

typings install dt~yargs --global --save

.ts archivos

Agregue esto a los archivos .ts:

import { argv } from 'yargs';

...

  let debug: boolean = argv.debug;

Esto debe hacerse en cada archivo .ts individualmente (incluso los tools/tasks/projectarchivos que se importan engulpfile.ts/js ).

correr

gulp build.dev --debug

O debajo de npmpasar el argumento a tragar:

npm run build.dev -- --debug

2

Pase argumentos desde la línea de comando

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

Luego corre tragando con:

$ gulp scripts --env development

Fuente


2
var isProduction = (process.argv.indexOf("production")>-1);

CLI gulp productionllama a mi tarea de producción y establece un indicador para cualquier condición.


1

Queríamos pasar un archivo de configuración diferente para diferentes entornos - uno para la producción , dev y pruebas . Este es el código en el archivo 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;
}

Este es el código en el archivo 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);
    }

Y luego correrlo tragar --env=testing


1

Ha pasado algún tiempo desde que se publicó esta pregunta, pero tal vez ayude a alguien.

Estoy usando GULP CLI 2.0.1 (instalado globalmente) y GULP 4.0.0 (instalado localmente) aquí es cómo lo hace sin ningún complemento adicional. Creo que el código se explica por sí mismo.

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;

Y correr desde la consola:

gulp availableTasks

Luego corre y ve las diferencias:

gulp availableTasks --verbose
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.