Có thể truyền cờ cho Gulp để nó chạy các tác vụ theo nhiều cách khác nhau không?


369

Thông thường trong các nhiệm vụ Gulp trông như thế này:

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

Có thể truyền cờ dòng lệnh cho gulp (đó không phải là một nhiệm vụ) và nó có chạy các nhiệm vụ một cách có điều kiện dựa trên điều đó không? Ví dụ

$ gulp my-task -a 1

Và sau đó trong gulpfile.js của tôi:

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
Vì nó đang chạy trong nút, nên bạn có thể sử dụng process.argvđể truy cập các đối số dòng lệnh.
zzzzBov

Câu trả lời:


528

Gulp không cung cấp bất kỳ loại sử dụng nào cho việc đó, nhưng bạn có thể sử dụng một trong nhiều lệnh phân tích cú pháp. Tôi thích yargs. Nên là:

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

Bạn cũng có thể kết hợp nó với gulp-ifđường ống có điều kiện, rất hữu ích cho việc xây dựng dev vs prod:

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

Và gọi với gulp my-js-taskhoặc gulp my-js-task --production.


45
Điều này nên được đề cập bằng cách nào đó @ github chính thức, công cụ cần thiết!
Tối đa

2
Điều này, video giải thích làm thế nào để đạt được điều này mà không cần yargs: youtube.com/watch?v=gRzCAyNrPV8
plankguy

9
Xin chào @plankguy, video rất hay. Cảm ơn. Nó cho thấy làm thế nào để phân tích các biến môi trường bằng tay, mà không có bất kỳ lib. Một điểm khác biệt nhỏ là video nói về các biến môi trường , trong khi ví dụ trên là về các đối số dòng lệnh , trong đó Yargs là một công cụ khác giúp đơn giản hóa mức tiêu thụ bằng cách trừu tượng hóa các biến phân tích.
Caio Cunha

12
Nếu bạn sử dụng npm run gulpthì bạn nên sử dụng nó như thế nào npm run gulp -- --production.
ivkremer

3
Điều này được đề cập @ githp gulub chính thức (theo nghĩa đen).
fracz

101

Biên tập

gulp-utilđang bị phản đối và nên tránh, vì vậy nó được đề nghị để sử dụng minimist thay vào đó, mà gulp-utilđã được sử dụng.

Vì vậy, tôi đã thay đổi một số dòng trong gulpfile của mình để xóa gulp-util:

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

gulp.task('styles', function() {
  return gulp.src(['src/styles/' + (argv.theme || 'main') + '.scss'])
    
});

Nguyên

Trong dự án của tôi, tôi sử dụng cờ sau:

gulp styles --theme literature

Gulp cung cấp một đối tượng gulp.envcho điều đó. Nó không được dùng trong các phiên bản mới hơn, vì vậy bạn phải sử dụng gulp-produc cho điều đó. Các nhiệm vụ trông như thế này:

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

Cài đặt môi trường có sẵn trong tất cả các nhiệm vụ. Vì vậy, tôi cũng có thể sử dụng cờ này trong nhiệm vụ đồng hồ:

gulp watch --theme literature

Và nhiệm vụ phong cách của tôi cũng hoạt động.

Ciao Ralf


6
gulp.envđang bị phản đối , như bạn có thể thấy thông báo nhật ký giao diện điều khiển khi chạy nó. Họ yêu cầu bạn sử dụng trình phân tích cú pháp của riêng bạn và đề xuất yargshoặc minimist.
Caio Cunha

2
Cảm ơn @CaioToOn cho gợi ý của bạn. Tôi đã cập nhật câu trả lời của mình và dự án của tôi nữa;)
RWAM

4
Bạn có thể rút ngắn util.env.theme ? util.env.theme : 'main'để util.env.theme || 'main'. Dù sao +1.
Renan

9
gulp-utilsử dụng minimistthư viện để phân tích đối số dòng lệnh. Vì vậy, nếu bạn đang sử dụng gulp-util, bạn không cần thêm một thư viện cho mục đích đó. Tài liệu: github.com/substack/minimist
Rockallite

57

Đây là một công thức nhanh tôi tìm thấy:

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

CLI

gulp scripts --env production

Tham chiếu gốc (không còn khả dụng nữa): https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-params-from-cli.md

Thay thế với tối thiểu hóa

Từ cập nhật tham khảo: https://github.com/gulpjs/gulp/blob/master/docs/recipes/pass-argument-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'));
});

CLI

gulp scripts --env production

2
Liên kết công thức đó dường như đã biến mất Thay vào đó, có một gói khác sử dụng gói minimist : pass-argument-from-cli.md . Điều đó có ý nghĩa vì bản thân gulp sử dụng minimist .
yuvilio

39

Có một cách rất đơn giản để làm on/offcờ mà không cần phân tích cú pháp. gulpfile.jschỉ là một tệp được thực thi như bất kỳ tệp nào khác, vì vậy bạn có thể làm:

var flags = {
  production: false
};

gulp.task('production', function () {
  flags.production = true;
});

Và sử dụng một cái gì đó như gulp-ifđể thực hiện có điều kiện một bước

gulp.task('build', function () {
  gulp.src('*.html')
    .pipe(gulp_if(flags.production, minify_html()))
    .pipe(gulp.dest('build/'));
});

Thực thi gulp buildsẽ tạo ra một html đẹp, trong khi gulp production buildsẽ thu nhỏ nó.


2
Ý tưởng tuyệt vời, tiết kiệm bằng cách sử dụng yargs, tôi đã mở rộng điều này bằng cách có một nhiệm vụ 'tiền sản xuất' đặt các vars và sau đó 'sản xuất' có một mảng phụ thuộc của ['xây dựng', 'tiền sản xuất']. Bằng cách đó, bạn có thể chạy "sản xuất".
Keegan 82

Đẹp! Tôi đang sử dụng điều này trước khi thiết lập luồng, vớigulp.task('mytask', function() { if (flags.myflag ) { flaggedtask } else { unflaggedask } });
henry

Tôi nghĩ rằng đây là cách tốt nhất để làm điều đó
gztomas

@ Keegan'shairstyle82 Tôi đã làm một cái gì đó tương tự nhưng phải sử dụng chuỗi chạy để đảm bảo không có điều kiện chủng tộc khi cài đặt thuộc tính flags.
CalMlynarchot

3
Nhược điểm của phương pháp này là bạn phải thay đổi gulpfile.js mỗi khi bạn muốn thay đổi các biến cờ, thay vì chỉ truyền các đối số cho lệnh gulp trong terminal.
jbyrd

33

Nếu bạn có một số đối số nghiêm ngặt (đã ra lệnh!), Thì bạn có thể nhận được chúng chỉ bằng cách kiểm tra process.argv.

var args = process.argv.slice(2);

if (args[0] === "--env" && args[1] === "production");

Thực hiện nó: gulp --env production

... Tuy nhiên, tôi nghĩ rằng đây là tooo nghiêm ngặt và không đạn! Vì vậy, tôi loay hoay một chút ... và kết thúc với chức năng tiện ích này:

function getArg(key) {
  var index = process.argv.indexOf(key);
  var next = process.argv[index + 1];
  return (index < 0) ? null : (!next || next[0] === "-") ? true : next;
}

Nó ăn một tên đối số và sẽ tìm kiếm trong này process.argv. Nếu không có gì được tìm thấy nó phun ra null. Mặt khác, nếu chúng không có đối số tiếp theo hoặc đối số tiếp theo là lệnh và không phải là giá trị (chúng tôi khác với dấu gạch ngang) trueđược trả về. (Đó là vì khóa tồn tại, nhưng không có giá trị). Nếu tất cả các trường hợp trước sẽ thất bại, giá trị đối số tiếp theo là những gì chúng ta nhận được.

> 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

Ok, đủ rồi ... Đây là một ví dụ đơn giản sử dụng 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"));
});

Chạy nó gulp --env production


Tên đối số nên được bắt đầu bằng dấu gạch ngang (es) : if (args[0] === '--env' && args[1] === 'production');, ít nhất là trong gulp 3.8.11
piotr_cz

@yckart - có lẽ bạn nên thêm yêu cầu ('..') cho getArg trong ví dụ mã của bạn.
jbyrd

7

Tôi đã xây dựng một plugin để đưa các tham số từ dòng lệnh vào tác vụ gọi lại.

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

// gulp mytask --production

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

Nếu ai đó tìm thấy một lỗi hoặc có một cải tiến đối với nó, tôi rất vui khi hợp nhất các PR.


4

Và nếu bạn đang sử dụng typecript ( gulpfile.ts) thì hãy làm điều này cho yargs(xây dựng trên câu trả lời tuyệt vời của @Caio Cunha https://stackoverflow.com/a/23038290/1019307 và các nhận xét khác ở trên):

Tải về

npm install --save-dev yargs

typings install dt~yargs --global --save

.ts các tập tin

Thêm phần này vào tệp .ts:

import { argv } from 'yargs';

...

  let debug: boolean = argv.debug;

Điều này phải được thực hiện trong từng tệp .ts riêng lẻ (ngay cả các tools/tasks/projecttệp được nhập vàogulpfile.ts/js ).

Chạy

gulp build.dev --debug

Hoặc npmthông qua arg thông qua để nuốt chửng:

npm run build.dev -- --debug

2

Truyền đối số từ dòng lệnh

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

Sau đó chạy gulp với:

$ gulp scripts --env development

Nguồn


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

CLI gulp productiongọi nhiệm vụ sản xuất của tôi và đặt cờ cho bất kỳ điều kiện nào.


1

Chúng tôi muốn thông qua một tập tin cấu hình khác nhau cho các môi trường khác nhau - một cho sản xuất , devthử nghiệm . Đây là mã trong tệp 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;
}

Đây là mã trong tệp 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);
    }

Và sau đó để chạy nó --env=testing


1

Đã được một thời gian kể từ khi câu hỏi này được đăng, nhưng có lẽ nó sẽ giúp được ai đó.

Tôi đang sử dụng GULP CLI 2.0.1 (được cài đặt trên toàn cầu) và GULP 4.0.0 (được cài đặt cục bộ) ở đây là cách bạn làm điều đó mà không cần bất kỳ plugin bổ sung nào. Tôi nghĩ rằng mã là khá tự giải thích.

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;

Và chạy từ bàn điều khiển:

gulp availableTasks

Sau đó chạy và xem sự khác biệt:

gulp availableTasks --verbose
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.