How to Pass Command Line Parameters to Gulp Tasks

Share this article

A soda cup with the Gulp.js logo, surrounded by tasks in the form of fast food items

I’m a big fan of Gulp.js and recent surveys indicate almost 44% of front-end developers are using Gulp tasks today.

Gulp’s simplicity is one of its most attractive features. You write a task function in your gulpfile.js:

gulp.task('doSomething', () => {

  // do something

});

then execute that task from the command line with gulp doSomething. Tasks can be as basic or complex as you like and include further sub-tasks.

However, it’s not possible to pass arguments on the command line which can be used by that task, e.g.

gulp doSomething --option1 "my string" --option2 123 --option3

(where option3 would equate to true)

The arguments would be passed to the Gulp application itself – not your task. Gulp knows nothing about these values so they’re not made available within gulpfile.js and cannot be examined or used within your task functions.

Do Gulp Tasks Need Arguments?

Generally not – otherwise, a facility to pass arguments to tasks would have been added many years ago! Gulp tasks are written in JavaScript so you can set value defaults within your code.

You can also analyze environment variables such as NODE_ENV. For example, you can check whether the value is set to production or similar on a live server. The setting can then be used to determine whether JavaScript source files are minified when the task runs, e.g.

// is this a development build?
const devBuild = ((process.env.NODE_ENV || 'development').trim().toLowerCase() === 'development');

// Gulp plugins
const
  stripdebug = require('gulp-strip-debug'),  // remove debugging code
  uglify = require('gulp-uglify');           // minify

// build JavaScript
gulp.task('js', () => {

  let jsbuild = gulp.src('src/js/*')
    .pipe(some-plugin1())
    .pipe(some-plugin2());

  // production server tasks
  if (!devBuild) {
    jsbuild = jsbuild
      .pipe(stripdebug())
      .pipe(uglify());
  }

  return jsbuild.pipe(gulp.dest('build/js/'));

});

You can now set export NODE_ENV=production on Linux/Mac or set NODE_ENV=production on Windows prior to running the gulp js task. It will then remove console.log and debugger statements before minifying your JavaScript files.

Finally, if you want a task to do something slightly different, you can create a new task. Tasks can be chained together to run in sequence as necessary, for example:

gulp.task('doSomething1', () => {

  return gulp.src('src/*')
    .pipe(some-plugin1())
    .pipe(gulp.dest('build/'));

});

// run doSomething1 first
gulp.task('doSomething2', [doSomething1], () => {

  // do something else
  return gulp.src('src/*')
    .pipe(some-plugin2())
    .pipe(gulp.dest('build/'));

});

Running gulp doSomething1 will execute the first task. Running gulp doSomething2 will execute both tasks in order because doSomething1 is defined as a dependency in the optional array following the task name.

Should We Ever Consider Arguments?

Arguments should be avoided when there are better alternative options. Your --option1 argument could become a valid command-line option in the next release of Gulp and have undesired consequences.

That said, there are always edge cases…

1. Passwords and security

You should normally avoid hard-coding credentials such as IDs and passwords into gulpfile.js. Consider the following task which deploys files to a server via FTP using the vinyl-ftp plug-in:

gulp.task('deploy', () => {

  let
    ftp = require('vinyl-ftp'),
    conn = ftp.create({
      host      : 'mysite.com',
      user      : 'myuserid',
      password  : 'mypassword',
      parallel  : 5
    }),
    glob = [
      'build/**/*'
    ],
    src = {
      base      : 'build/',
      buffer    : false
    },
    remotePath = '/public_html/';

  return gulp.src(glob, src)
    .pipe(conn.newerOrDifferentSize(remotePath))
    .pipe(conn.dest(remotePath));

});

(Admittedly, FTP is not a great deployment method but it’s still used by many developers and can be the only option on some hosts.)

There are several problems with this approach:

  1. The FTP host, user ID, password, and path are hard-coded into the file. That would lead to security issues if the code were stored in a public GitHub repository and could be viewed, cloned and run by anyone.
  2. Any developer can run gulp deploy at any time from any device. That’s unlikely to be desirable for larger teams who want to control when deployments occur.
  3. If the credentials change, you must manually update gulpfile.js to ensure the deployment task still works.

2. Differing source, build or task locations

Gulp can be used for something other than typical website tasks. For example, you might have general tasks to wipe folders, create databases, transfer files, etc. Hard-coding something like a database or folder name would make those tasks less useful.

3. Complex tasks

Imagine a complex task involving dozens of plug-ins. If it’s not practical to split it into multiple sub-tasks, it may become difficult to add configuration options without editing gulpfile.js directly prior to running the task.

You may be able to think of further edge cases (comments welcome!)

How to Pass Arguments to Your Gulp.js Tasks

The process.argv property in Node.js returns an array containing the the process, script and all command line arguments. For example, gulp task1 --a 123 --b "my string" --c returns the following array (values may differ depending on your OS and set-up):

[
'/usr/bin/nodejs',
'/home/user/.node_modules_global/bin/gulp',
'task1',
'--a',
'123',
'--b',
'my string',
'--c'
]

This array can be parsed in gulpfile.js. The following code creates an object named arg containing argument values:

// fetch command line arguments
const arg = (argList => {

  let arg = {}, a, opt, thisOpt, curOpt;
  for (a = 0; a < argList.length; a++) {

    thisOpt = argList[a].trim();
    opt = thisOpt.replace(/^\-+/, '');

    if (opt === thisOpt) {

      // argument value
      if (curOpt) arg[curOpt] = opt;
      curOpt = null;

    }
    else {

      // argument name
      curOpt = opt;
      arg[curOpt] = true;

    }

  }

  return arg;

})(process.argv);

The function loops through the process.argv array. When it encounters a value preceded with one or more dashes, it creates a new named value in the arg object which is set to true. When it encounters a value without dashes, it sets the previous named value (if available) to that string.

When we run gulp task1 --a 123 --b "my string" --c, the arg object is set to:

{
  "a": "123",
  "b": "my string",
  "c": true
}

We can, therefore, examine and use those values as required.

Assuming arg is set at the top of gulpfile.js, we can rewrite our FTP deployment task so we can pass:

  • the user ID as a --user or --u argument
  • the password as a --password or --p argument
gulp.task('deploy', () => {

  let
    ftp = require('vinyl-ftp'),
    conn = ftp.create({
      host      : 'mysite.com',
      user      : arg.user || arg.u,      // command line option
      password  : arg.password || arg.p,  // command line option
      parallel  : 5
    }),
    glob = [
      'build/**/*'
    ],
    src = {
      base      : 'build/',
      buffer    : false
    },
    remotePath = '/public_html/';

  return gulp.src(glob, src)
    .pipe(conn.newerOrDifferentSize(remotePath))
    .pipe(conn.dest(remotePath));

});

A deployment would only occur if we run the task with appropriate FTP credentials, e.g.

gulp deploy --u myuserid --p mypassword

Wrapping Up

As we’ve seen, with a little bit of custom code it is possible to pass parameters in to Gulp tasks. Although it’s often not necessary for your tasks to receive arguments, we saw there are certain cases where it’s useful. It’s definitely a good technique to have in your toolkit.

The argument parsing code can be used for any Node.js command line process. However, the commander module offers considerably more sophistication should you require it in non-Gulp projects.

I hope you find this useful. Of course, just because you can pass arguments to Gulp tasks, it doesn’t follow that you should! If you come up with any more good use cases for this, let me know in the comments.

This article was peer reviewed by Tim Severien. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Frequently Asked Questions (FAQs) about Passing Parameters to Gulp Tasks

How can I pass parameters to Gulp tasks from the command line?

Passing parameters to Gulp tasks from the command line can be achieved using the process.argv array. This array contains the command line arguments that were passed when Node.js process was launched. The first two elements of this array are the path to the Node.js executable and the path to the Gulp file. Any additional parameters will be added to this array starting from the third position. You can access these parameters in your Gulp tasks by indexing into the process.argv array.

Can I use a package to handle command line arguments in Gulp?

Yes, you can use a package like yargs or minimist to handle command line arguments in Gulp. These packages parse command line arguments into a more usable format, making it easier to work with them in your Gulp tasks. For example, if you use yargs, you can access the command line arguments as properties of the yargs.argv object.

How can I use flags in Gulp tasks?

Flags can be passed to Gulp tasks from the command line by prefixing the flag name with two dashes. For example, you can pass a ‘production’ flag to a Gulp task like this: gulp build –production. In your Gulp task, you can check if this flag was set using the process.argv array or a package like yargs or minimist.

Can I pass multiple parameters to a Gulp task?

Yes, you can pass multiple parameters to a Gulp task from the command line. These parameters will be added to the process.argv array in the order they were passed. You can access these parameters in your Gulp task by indexing into the process.argv array.

How can I use command line arguments in a Gulp task?

Command line arguments can be used in a Gulp task by accessing them through the process.argv array or a package like yargs or minimist. You can use these arguments to control the behavior of your Gulp tasks. For example, you can use a ‘production’ flag to minify your code in a build task.

Can I use environment variables in Gulp tasks?

Yes, you can use environment variables in Gulp tasks. These variables can be accessed through the process.env object. This can be useful if you want to pass sensitive information to your Gulp tasks, like API keys, without exposing them in your command line arguments.

How can I handle errors in Gulp tasks?

Errors in Gulp tasks can be handled using the .on(‘error’) method. This method takes a callback function that will be called when an error occurs. In this callback function, you can log the error and end the task to prevent Gulp from crashing.

Can I run multiple Gulp tasks in sequence?

Yes, you can run multiple Gulp tasks in sequence using the gulp.series() method. This method takes an array of task names and runs them in the order they are defined.

Can I run multiple Gulp tasks in parallel?

Yes, you can run multiple Gulp tasks in parallel using the gulp.parallel() method. This method takes an array of task names and runs them all at the same time.

How can I define default Gulp tasks?

Default Gulp tasks can be defined using the gulp.task() method with ‘default’ as the task name. This task will be run when you execute the gulp command without any task names. You can use this task to run a series of other tasks by default.

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

cliGulpnilsonj
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week