是否可以将标志传递给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));
});

11
当它在节点中运行时,您可能会使用它process.argv来访问命令行参数。
zzzzBov 2014年

Answers:


528

Gulp对此不提供任何实用程序,但是您可以使用许多命令args解析器之一。我喜欢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来有条件地传输流,这对于开发与生产产品非常有用:

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,必不可少的东西!
2014年

2
此视频介绍了如何不yargs实现这一目标:youtube.com/watch?v=gRzCAyNrPV8
plankguy

9
@plankguy,您好,视频非常棒。谢谢。它显示了如何在没有任何lib的情况下手动解析环境变量。一个小差异是视频是关于环境变量的,而上面的示例是关于命令行参数的,Yargs是另一个工具,它通过抽象化变量解析来帮助简化消耗。
Caio Cunha 2014年

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

我的样式任务也有效。

乔·拉尔夫


6
gulp.env已弃用,如运行时的控制台日志消息所示。他们要求您使用自己的解析器并建议yargsminimist
Caio Cunha 2014年

2
感谢@CaioToOn的提示。我也更新了答案和项目;)
RWAM 2014年

4
您可以缩短util.env.theme ? util.env.theme : 'main'util.env.theme || 'main'。无论如何+1。
雷南2015年

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

命令行界面

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

命令行界面

gulp scripts --env production

2
该配方链接现在似乎消失了。还有另一种使用minimist包的方法:pass-arguments-from-cli.md。这是有道理的,因为gulp本身使用的是极简主义
yuvilio 2014年

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可以节省资源,我通过执行“生产前”任务来设置vars,从而扩展了此功能,然后“生产”具有['build','生产前']的依赖项数组。这样,您就可以运行“大批量生产”。
基冈82

真好!在设置视频流之前,我正在使用此功能gulp.task('mytask', function() { if (flags.myflag ) { flaggedtask } else { unflaggedask } });
henry 2016年

我认为这是
大吃一惊的

@ 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


参数名称的前缀应为dash(es)if (args[0] === '--env' && args[1] === 'production');:,至少在gulp 3.8.11
piotr_cz

@yckart-您可能应该在代码示例中为getArg添加require('..')。
jbyrd

7

我构建了一个插件,用于将命令行中的参数注入到任务回调中。

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

// gulp mytask --production

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

如果有人发现错误或对其进行了改进,我很乐意合并PR。


4

如果您使用的是打字稿(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将arg传递到gulp:

npm run build.dev -- --debug

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:

$ gulp scripts --env development

资源


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

CLI gulp production调用我的生产任务,并为任何条件设置一个标志。


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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.