204

Normally we can run gulp task from console via something like gulp mytask. Is there anyway that I can pass in parameter to gulp task? If possible, please show example how it can be done.

user1995781
  • 16,821
  • 41
  • 122
  • 221
  • 5
    https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-arguments-from-cli.md – Heikki Feb 16 '15 at 10:40
  • Does this answer your question? [Is it possible to pass a flag to Gulp to have it run tasks in different ways?](https://stackoverflow.com/questions/23023650/is-it-possible-to-pass-a-flag-to-gulp-to-have-it-run-tasks-in-different-ways) – Barbu Barbu Jan 17 '20 at 10:57

12 Answers12

282

It's a feature programs cannot stay without. You can try yargs.

npm install --save-dev yargs

You can use it like this:

gulp mytask --production --test 1234

In the code, for example:

var argv = require('yargs').argv;
var isProduction = (argv.production === undefined) ? false : true;

For your understanding:

> gulp watch
console.log(argv.production === undefined);  <-- true
console.log(argv.test === undefined);        <-- true

> gulp watch --production
console.log(argv.production === undefined);  <-- false
console.log(argv.production);                <-- true
console.log(argv.test === undefined);        <-- true
console.log(argv.test);                      <-- undefined

> gulp watch --production --test 1234
console.log(argv.production === undefined);  <-- false
console.log(argv.production);                <-- true
console.log(argv.test === undefined);        <-- false
console.log(argv.test);                      <-- 1234

Hope you can take it from here.

There's another plugin that you can use, minimist. There's another post where there's good examples for both yargs and minimist: (Is it possible to pass a flag to Gulp to have it run tasks in different ways?)

quotesBro
  • 4,240
  • 2
  • 27
  • 38
Ethan
  • 4,512
  • 1
  • 24
  • 32
  • 13
    Really well written answer, thanks for the examples! – Allen Rice May 17 '15 at 20:37
  • how does one access this in javascript? – vini Mar 10 '16 at 14:52
  • If you use gulp with yargs, notice the following: If you have a task 'customer' and wan't to use yargs build in Parameter checking for required commands: command("customer","Create a customer directory") – suther Jan 01 '17 at 00:11
  • See my comment below, if you want to use the yargs built in parameter check for required 'commands' together with gulp: http://stackoverflow.com/a/41412558/1256697 – suther Jan 01 '17 at 00:36
  • 5
    `(argv.production === undefined) ? false : true;` is equivalent to `argv.production !== undefined`. – JimmyMcHoover Jul 20 '17 at 09:32
  • @Ragnagord Yes, that's right. I wrote like that for easy understanding, the purpose behind this answer. – Ethan Mar 02 '18 at 04:55
143

If you want to avoid adding extra dependencies, I found node's process.argv to be useful:

gulp.task('mytask', function() {
    console.log(process.argv);
});

So the following:

gulp mytask --option 123

should display:

[ 'node', 'path/to/gulp.js', 'mytask', '--option', '123']

If you are sure that the desired parameter is in the right position, then the flags aren't needed.** Just use (in this case):

var option = process.argv[4]; //set to '123'

BUT: as the option may not be set, or may be in a different position, I feel that a better idea would be something like:

var option, i = process.argv.indexOf("--option");
if(i>-1) {
    option = process.argv[i+1];
}

That way, you can handle variations in multiple options, like:

//task should still find 'option' variable in all cases
gulp mytask --newoption somestuff --option 123
gulp mytask --option 123 --newoption somestuff
gulp mytask --flag --option 123

** Edit: true for node scripts, but gulp interprets anything without a leading "--" as another task name. So using gulp mytask 123 will fail because gulp can't find a task called '123'.

Trevedhek
  • 3,502
  • 2
  • 16
  • 14
  • 1
    There's a typo in "var option, i = process,argv.indexOf("--option");". I believe it should be proccess.argv. – Luis Paulo Lohmann Oct 16 '15 at 16:04
  • Ah, so it should. Corrected. Thanks @luis – Trevedhek Oct 17 '15 at 20:30
  • I just wanted to check for the --dev flag, so I could distinguish between production and lower environments. This does the trick without adding extra dependencies. Thank! – b01 Oct 30 '15 at 19:50
  • 1
    For me, `gulp myTask --production` results in `process.argv` equal to `[pathToNode, pathToGulp, 'myTask', '--production']` – Sung Cho Apr 16 '16 at 06:21
  • Hm. Me too. Not sure if that has changed or I just missed it. Answer changed - thank you @sung-won-cho – Trevedhek Apr 17 '16 at 19:48
  • 3
    It has probably changed, I've seen some old examples with the same difference. Anyway, you can just debug it and see for your case. This should be the accepted answer as it has zero dependencies.. – Juan May 02 '17 at 00:06
  • A little thing more. When call with npm script: `npm run build -- --production` with the npm build script as `"scripts": { "build": "gulp build" }` – Tristan Nov 04 '17 at 13:32
  • I use eval Command `gulp dev` Gulp File `gulp.task(eval(`"${STAGE}"`), function () { return tsProject.src() .pipe(tsProject()) .js.pipe(gulp.dest( STAGE === "dev" ? 'dist/debug' : 'dist/release' )); });` Output: `> gulp dev Building for dev stage [14:11:15] Using gulpfile ~/projects/project/gulpfile.js [14:11:15] Starting 'dev'... [14:11:16] Finished 'dev' after 1.15 s` – Jonathan Mar 01 '20 at 22:12
19

Passing a parameter to gulp can mean a few things:

  • From the command line to the gulpfile (already exemplified here).
  • From the main body of the gulpfile.js script to gulp tasks.
  • From one gulp task to another gulp task.

Here's an approach of passing parameters from the main gulpfile to a gulp task. By moving the task that needs the parameter to it's own module and wrapping it in a function (so a parameter can be passed).:

// ./gulp-tasks/my-neat-task.js file
module.exports = function(opts){

  opts.gulp.task('my-neat-task', function(){
      console.log( 'the value is ' + opts.value );
  });

};
//main gulpfile.js file

//...do some work to figure out a value called val...
var val = 'some value';

//pass that value as a parameter to the 'my-neat-task' gulp task
require('./gulp-tasks/my-neat-task.js')({ gulp: gulp, value: val});

This can come in handy if you have a lot of gulp tasks and want to pass them some handy environmental configs. I'm not sure if it can work between one task and another.

yuvilio
  • 2,997
  • 29
  • 33
17

There's an official gulp recipe for this using minimist.

https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-arguments-from-cli.md

The basics are using minimist to separate the cli arguments and combine them with known options:

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

Which would parse something like

$ gulp scripts --env development

More complete info in the recipe.

RobW
  • 8,857
  • 4
  • 37
  • 40
  • 1
    Why is the garbage on the top of the list and the proper solution on the bottom not getting upvoted? sigh – DDD Aug 26 '17 at 22:36
14

If you want to use environment params and other utils as well such as log, you can use gulp-util

/* 
  $npm install gulp-util --save-dev
  $gulp --varName 123
*/
var util = require('gulp-util');
util.log(util.env.varName);

Update

gulp-util is now deprecated. You can use minimist instead.

var argv = require('minimist')(process.argv.slice(2));
console.dir(argv);
Quy Tang
  • 3,659
  • 1
  • 25
  • 39
5

@Ethan's answer would completely work. From my experience, the more node way is to use environment variables. It's a standard way to configure programs deployed on hosting platforms (e.g. Heroku or Dokku).

To pass the parameter from the command line, do it like this:

Development: gulp dev

Production: NODE_ENV=production gulp dev

The syntax is different, but very Unix, and it's compatible with Heroku, Dokku, etc.

You can access the variable in your code at process.env.NODE_ENV

MYAPP=something_else gulp dev

would set

process.env.MYAPP === 'something_else'

This answer might give you some other ideas.

Community
  • 1
  • 1
Michael Cole
  • 13,473
  • 4
  • 66
  • 81
4

Here is my sample how I use it. For the css/less task. Can be applied for all.

var cssTask = function (options) {
  var minifyCSS = require('gulp-minify-css'),
    less = require('gulp-less'),
    src = cssDependencies;

  src.push(codePath + '**/*.less');

  var run = function () {
    var start = Date.now();

    console.log('Start building CSS/LESS bundle');

    gulp.src(src)
      .pipe(gulpif(options.devBuild, plumber({
        errorHandler: onError
      })))
      .pipe(concat('main.css'))
      .pipe(less())
      .pipe(gulpif(options.minify, minifyCSS()))
      .pipe(gulp.dest(buildPath + 'css'))
      .pipe(gulpif(options.devBuild, browserSync.reload({stream:true})))
      .pipe(notify(function () {
        console.log('END CSS/LESS built in ' + (Date.now() - start) + 'ms');
      }));
  };

  run();

  if (options.watch) {
    gulp.watch(src, run);
  }
};

gulp.task('dev', function () {
  var options = {
    devBuild: true,
    minify: false,
    watch: false
  };

  cssTask (options);
});
Lynx
  • 51
  • 4
3

Here is another way without extra modules:

I needed to guess the environment from the task name, I have a 'dev' task and a 'prod' task.

When I run gulp prod it should be set to prod environment. When I run gulp dev or anything else it should be set to dev environment.

For that I just check the running task name:

devEnv = process.argv[process.argv.length-1] !== 'prod';
antoni
  • 3,652
  • 25
  • 37
2

If you use gulp with yargs, notice the following:

If you have a task 'customer' and wan't to use yargs build in Parameter checking for required commands:

.command("customer <place> [language]","Create a customer directory") call it with:

gulp customer --customer Bob --place Chicago --language english

yargs will allway throw an error, that there are not enough commands was assigned to the call, even if you have!! —

Give it a try and add only a digit to the command (to make it not equal to the gulp-task name)... and it will work:

.command("customer1 <place> [language]","Create a customer directory")

This is cause of gulp seems to trigger the task, before yargs is able to check for this required Parameter. It cost me surveral hours to figure this out.

Hope this helps you..

suther
  • 8,610
  • 2
  • 43
  • 79
0

I know I am late to answer this question but I would like to add something to answer of @Ethan, the highest voted and accepted answer.

We can use yargs to get the command line parameter and with that we can also add our own alias for some parameters like follow.

var args = require('yargs')
    .alias('r', 'release')
    .alias('d', 'develop')
    .default('release', false)
    .argv;

Kindly refer this link for more details. https://github.com/yargs/yargs/blob/HEAD/docs/api.md

Following is use of alias as per given in documentation of yargs. We can also find more yargs function there and can make the command line passing experience even better.

.alias(key, alias)

Set key names as equivalent such that updates to a key will propagate to aliases and vice-versa.

Optionally .alias() can take an object that maps keys to aliases. Each key of this object should be the canonical version of the option, and each value should be a string or an array of strings.

Code Spark
  • 178
  • 14
0

There is certainly a shorter notation, but that was my approach:

gulp.task('check_env', function () {
  return new Promise(function (resolve, reject) {
    // gulp --dev
    var env = process.argv[3], isDev;
    if (env) {
      if (env == "--dev") {
        log.info("Dev Mode on");
        isDev = true;
      } else {
        log.info("Dev Mode off");
        isDev = false;
      }
    } else {
      if (variables.settings.isDev == true) {
        isDev = true;
      } else {
        isDev = false;
      }
    }
    resolve();
  });
});

If you want to set the env based to the actual Git branch (master/develop):

gulp.task('set_env', function (cb) {
  exec('git rev-parse --abbrev-ref HEAD', function (err, stdout, stderr) {
    const git__branch = stdout.replace(/(\r\n|\n|\r)/gm, ""),
          regex__feature = new RegExp('feature/feature-*');

    if (git__branch == "develop") {
      log.info("‍Develop Branch");
      isCompressing = false;
    } else if (git__branch == "master") {
      log.info("Master Branch");
      isCompressing = true;
    } else if (regex__feature.test(git__branch) === true){
      log.info("✨Feature Branch");
      isCompressing = true;
    }else{

      //TODO: check for other branch
      log.warn("Unknown " + git__branch + ", maybe hotfix?");
      //isCompressing = variables.settings.isCompressing;
    }
    log.info(stderr);
    cb(err);
  });
  return;
})

P.s. For the log I added the following:

  var log = require('fancy-log');

In Case you need it, thats my default Task:

gulp.task('default',
  gulp.series('set_env', gulp.parallel('build_scss', 'minify_js', 'minify_ts', 'minify_html', 'browser_sync_func', 'watch'),
    function () {
    }));

Suggestions for optimization are welcome.

Julian
  • 65
  • 8
-2

Just load it into a new object on process .. process.gulp = {} and have the task look there.

Kirk Strobeck
  • 15,873
  • 14
  • 70
  • 107