【问题标题】:Is it possible to pass a flag to Gulp to have it run tasks in different ways?是否可以将标志传递给 Gulp 以使其以不同的方式运行任务?
【发布时间】:2014-05-26 06:17:03
【问题描述】:

通常在 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));
});

【问题讨论】:

  • 因为它在节点中运行,您可能可以使用process.argv 来访问命令行参数。

标签: javascript node.js gulp


【解决方案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

【讨论】:

    【解决方案2】:

    编辑

    gulp-utildeprecated 应该避免使用,所以建议使用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
    

    我的样式任务也有效。

    Ciao 拉尔夫

    【讨论】:

    • gulp.env is being deprecated,正如您在运行它时从控制台日志消息中看到的那样。他们要求您使用自己的解析器并建议 yargsminimist
    • 感谢@CaioToOn 的提示。我也更新了我的答案和我的项目;)
    • 您可以将util.env.theme ? util.env.theme : 'main' 缩短为util.env.theme || 'main'。无论如何+1。
    • gulp-util 利用minimist 库进行命令行参数解析。因此,如果您使用gulp-util,则不需要为此目的使用额外的库。文档:github.com/substack/minimist
    【解决方案3】:

    如果您使用的是打字稿 (gulpfile.ts),请为 yargs 执行此操作(基于 @Caio Cunha 的出色回答 https://stackoverflow.com/a/23038290/1019307 和上述其他 cmets):

    安装

    npm install --save-dev yargs
    
    typings install dt~yargs --global --save
    

    .ts 文件

    将此添加到 .ts 文件中:

    import { argv } from 'yargs';
    
    ...
    
      let debug: boolean = argv.debug;
    

    这必须在每个 .ts 文件中单独完成(即使是导入到 gulpfile.ts/js 中的 tools/tasks/project 文件)。

    运行

    gulp build.dev --debug
    

    或在npm 下将arg 传递给gulp:

    npm run build.dev -- --debug
    

    【讨论】:

      【解决方案4】:

      我们希望为不同的环境传递不同的配置文件——一个用于生产dev测试。这是 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);
          }

      然后运行它 gulp --env=testing

      【讨论】:

        【解决方案5】:

        如果您有一些严格的(有序的!)参数,那么您只需检查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 将返回。 (那是因为密钥存在,但没有价值)。如果之前的所有情况都失败了,那么下一个参数值就是我们得到的。

        &gt; 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

        【讨论】:

        • 参数名称应以破折号为前缀:if (args[0] === '--env' &amp;&amp; args[1] === 'production');,至少在 gulp 3.8.11 中
        • @yckart - 您可能应该在代码示例中为 getArg 添加 require('..')。
        【解决方案6】:
        var isProduction = (process.argv.indexOf("production")>-1);
        

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

        【讨论】:

          【解决方案7】:

          这是我找到的快速食谱:

          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
          

          【讨论】:

          【解决方案8】:

          有一种非常简单的方法可以在不解析参数的情况下执行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 会缩小它。

          【讨论】:

          • 好主意,使用 yargs 保存,我通过设置变量的“预生产”任务扩展了这一点,然后“生产”具有 ['build','pre -生产']。这样你就可以运行“gulp production”。
          • 不错!我在设置流之前使用它,gulp.task('mytask', function() { if (flags.myflag ) { flaggedtask } else { unflaggedask } });
          • 我认为这是吞咽的方式
          • @Keegan'shairstyle82 我做了类似的事情,但必须使用run-sequence 来确保在设置flags 的属性时没有竞争条件。
          • 这种方法的缺点是每次要更改标志变量时都必须更改 gulpfile.js,而不是只在终端中将参数传递给 gulp 命令。
          【解决方案9】:

          从命令行传递参数

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

          Source

          【讨论】:

            【解决方案10】:

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

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

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

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

            【讨论】:

              【解决方案11】:

              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-taskgulp my-js-task --production

              【讨论】:

              • 这应该以某种方式提到@官方 gulp github,必不可少的东西!
              • 这个,视频解释了如何在没有 yargs 的情况下实现这一点:youtube.com/watch?v=gRzCAyNrPV8
              • 嗨@plankguy,视频非常好。谢谢。它展示了如何在没有任何库的情况下手动解析环境变量。一个小的区别是视频是关于环境变量的,而上面的例子是关于命令行参数的,其中Yargs是另一个工具,它通过抽象变量解析。
              • 如果你使用npm run gulp,那么你应该像npm run gulp -- --production一样使用它。
              • 这是@official gulp github 提到的(字面意思)。
              猜你喜欢
              • 2016-10-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-01-16
              • 2012-12-26
              • 1970-01-01
              相关资源
              最近更新 更多