传递参数给Gulp任务

226

通常我们可以通过类似 gulp mytask 的方式在控制台中运行 gulp 任务。有没有什么办法可以向 gulp 任务传递参数?如果可能的话,请举一个例子说明如何实现。


5
以下是需要翻译的内容:

从命令行传递参数

如果你想从命令行传递参数给 gulp 任务,可以使用 yargs 模块。下面是一个例子:const gulp = require('gulp'); const rename = require('gulp-rename'); const argv = require('yargs').argv; gulp.task('rename', function() { return gulp.src('src/**/*') .pipe(rename(function(path) { path.basename += "-" + argv.suffix; })) .pipe(gulp.dest('dist')); });在这个例子中,我们定义了一个 gulp 任务来重命名文件。我们使用 yargs 模块来获取从命令行传递过来的 --suffix 参数,并把它添加到文件名的末尾。这样,当我们运行以下命令时:gulp rename --suffix foo所有的文件都会被重命名并添加后缀 -foo。请注意,我们使用 -- 来分隔 gulp 命令和我们要传递的参数。然后,我们可以使用 argv 对象来访问这些参数。
- Heikki
12个回答

310

这是一个程序不能缺少的功能。你可以尝试使用yargs

npm install --save-dev yargs

您可以像这样使用它:
gulp mytask --production --test 1234

在代码中,例如:
var argv = require('yargs').argv;
var isProduction = (argv.production === undefined) ? false : true;

为了您的理解:

> 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

希望你能接着做下去。

还有另一个插件可以使用,叫做minimist。这里有另一篇文章,其中包含了yargs和minimist的好例子:(有没有可能通过传递标志给Gulp来以不同的方式运行任务?)


16
非常好的回答,感谢提供示例! - Allen Rice
在JavaScript中如何访问这个? - vini
如果您想要在gulp中使用yargs内置的参数检查来检查所需的“commands”,请参见我的下面的评论:https://dev59.com/dF4b5IYBdhLWcg3w61Z3#41412558 - suther
6
(argv.production === undefined) ? false : true;等价于argv.production !== undefined - JimmyMcHoover
package.json 文件中,处理 gulp 命令行参数的脚本会是什么样子? - Chris F
显示剩余2条评论

150

如果您想避免添加额外的依赖关系,我发现Node.js的process.argv很有用:

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

所以以下内容:

gulp mytask --option 123

应该展示:

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

如果您确定所需参数位于正确位置,则不需要使用标志。** 在这种情况下,只需使用:

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

然而:由于选项可能未设置或可能处于不同的位置,我认为更好的想法是:

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

这样做,您就可以处理多个选项的变化,例如:

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

**编辑:对于node脚本来说是正确的,但gulp解释没有前导“--”的任何内容都是另一个任务名称。因此,使用 gulp mytask 123 将失败,因为gulp找不到名为'123'的任务。


1
"var option, i = process.argv.indexOf("--option");"中有一个错别字。我相信应该是process.argv。 - Luis Paulo Lohmann
啊,应该是这样的。已经更正了。谢谢@luis。 - Trevedhek
1
对我来说,运行 gulp myTask --production 会导致 process.argv 等于 [pathToNode, pathToGulp, 'myTask', '--production'] - mc9
嗯,我也是。不确定是否有所改变或者我只是错过了。答案已更改 - 感谢@sung-won-cho。 - Trevedhek
3
可能已经改变了,我看过一些旧的例子,也有相同的差异。无论如何,你可以对其进行调试并查看你的情况。这应该是被接受的答案,因为它没有任何依赖关系。 - chesscov77
显示剩余4条评论

23

1
为什么垃圾内容总是排在列表的前面,而正确的解决方案却得不到赞同呢?唉。 - Playdome.io

19

在gulp中传递参数可以有几种意思:

  • 从命令行传递到gulpfile(如本例所示)。
  • 从gulpfile.js脚本的主体传递到gulp任务。
  • 从一个gulp任务传递到另一个gulp任务。

以下是一种从gulpfile主体传递参数到gulp任务的方法。通过将需要参数的任务移动到自己的模块中并将其包装在一个函数中(以便可以传递参数):

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

如果您有很多Gulp任务并希望传递一些方便的环境配置,那么这将非常实用。我不确定它是否可以在一个任务和另一个任务之间起作用。


14

如果你想要使用环境参数和其他实用工具如日志,你可以使用gulp-util


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

更新

gulp-util现已过时。您可以使用minimist代替。

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

1
gulp-util自2016年以来已经被弃用。 - valdeci

5

@Ethan的回答完全可行。根据我的经验,使用环境变量是更多的节点方式。这是一种在托管平台上配置程序的标准方式(例如Heroku或Dokku)。

要从命令行传递参数,请按以下方式操作:

开发: gulp dev

生产: NODE_ENV=production gulp dev

语法不同,但非常Unix,并且与Heroku、Dokku等兼容。

您可以在代码中访问变量:process.env.NODE_ENV

MYAPP=something_else gulp dev

会设置

process.env.MYAPP === 'something_else'

这个回答可能会给您一些其他想法。


4

以下是我使用它的示例。适用于css/less任务。可应用于所有。

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

3
如果您使用gulp和yargs,请注意以下内容:
如果您有一个任务'customer'并希望使用yargs内置的参数检查来检查必需的命令: .command("customer <place> [language]","创建客户目录")
请使用以下调用:
gulp customer --customer Bob --place Chicago --language english

yargs会始终抛出一个错误,即使你已经指定了足够的命令调用,也会提示命令不足!!尝试给该命令添加一个数字(以使其与gulp任务名称不相等)...... 然后它就可以工作了:

.command("customer1 <place> [language]","创建客户目录")

这是因为gulp似乎在yargs能够检查此必需参数之前触发了该任务。我花费了几个小时才找到这个问题。

希望这可以帮助你解决问题。


3
这里还有一种方法,不需要额外的模块:
我需要从任务名称中猜测环境,我有一个' dev '任务和一个' prod '任务。
当我运行gulp prod时,它应该被设置为生产环境。 当我运行gulp dev或任何其他内容时,它应该被设置为开发环境。
为此,我只需检查正在运行的任务名称:
devEnv = process.argv[process.argv.length-1] !== 'prod';

0

我知道我回答这个问题有点晚,但我想为@Ethan的回答添加一些内容,他的回答是最高票和被接受的。

我们可以使用yargs来获取命令行参数,并且我们还可以为某些参数添加自己的别名,如下所示。

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

请参考以下链接以获取更多详细信息。 https://github.com/yargs/yargs/blob/HEAD/docs/api.md

根据 yargs 文档,以下是别名的用法。我们还可以在那里找到更多的 yargs 函数,并使命令行传递体验更好。

.alias(key, alias)

将键名设置为等效,以便对键的更新将传播到别名,反之亦然。

可选地,.alias() 可以接受一个将键映射到别名的对象。该对象的每个键都应该是选项的规范版本,每个值都应该是一个字符串或字符串数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接