Reputation: 2882
I'm trying to conditionally pipe a file stream based on the value of a variable, as a way to define two separate build environments (ie. development and production).
Some tasks can be run individually with a command-line flag like so:
gulp scripts --env production
And will then do some production-only pipeline steps:
gulp.task('scripts', function() {
var jsFilter = filter(['*.js']),
appFiles;
return gulp.src(appFiles)
.pipe(jsFilter)
.pipe(concat('application-build.js'))
.pipe(gulpif(env === 'production', uglify()))
.pipe(size())
.pipe(gulpif(env === 'production', gulp.dest('dist/js'), gulp.dest('tmp/js')))
.pipe(browserSync.reload({ stream: true }));
});
I have a build
task that calls a number of other tasks as dependencies (including this scripts
task for instance). I want this build
task to assign a variable (env
, in this case) before running task dependencies. Which means that this:
gulp.task('build', ['scripts', 'styles', 'otherstuff'], function() {
env = 'production';
}
doesn't work, because the dependencies are run before the body of the task.
I currently have it implemented with gulp.start
:
gulp.task('build', function() {
env = 'production';
gulp.start('scripts');
});
But the .start
method isn't actually part of gulp's public API - it comes from Orchestrator - and isn't intended to be used for anything. Plus, the equivalent method gulp.run
was deprecated from the API awhile ago.
So I'm wondering - is there another way I could assign a variable in a task before running its dependencies?
(Or maybe there's a better way to to implement something like build environments in gulp?)
Upvotes: 20
Views: 17273
Reputation: 1
I disagree with @Justin. Defining an environmental variable with a task is a hackjob of an idea. This is better done with gutil.env
this way.
gulp --env prod task
gulp.task( 'myTask', () => { console.log( gutil.env.env ) } )
Now from this point, you have gulp.env.env
set.
Or, alternatively you can do like this example in this ticket.. which addresses this from the developers of Gulp which first suggest to use an environmental variable, but provide this idiom..
function js(shouldMinify) {
return gulp.src('./js/*.js')
.pipe(concat('app.js'))
.pipe(gulpif(shouldMinify, uglify()))
.pipe(gulp.dest('js'));
});
gulp.task('develop', function () {
shouldMinify = false;
return js(shouldMinify);
});
gulp.task('build', function () {
shouldMinify = true;
return js(shouldMinify);
});
That same developer (phated) always says to use env...
Not to mention, you should control this type of logic with environment variables or command line flags. - phated
Presumably, he's referring to the use of gutil.noop()
in gulp-util
's docs:
// gulp should be called like this :
// $ gulp --type production
gulp.task('scripts', function() {
gulp.src('src/**/*.js')
.pipe(concat('script.js'))
// LOOK BELOW: if we don't send to uglify, we push to noop stream.
.pipe(gutil.env.type === 'production' ? uglify() : gutil.noop())
.pipe(gulp.dest('dist/'));
});
Upvotes: 21
Reputation: 5643
You could create a task specifically to set the environment and run it before your other tasks.
gulp.task('set-production', function() {
env = 'production';
});
// Doesn't quite work because tasks are run in parallel
gulp.task('build', ['set-production', 'scripts', 'styles', 'otherstuff']);
The problem here is that your tasks will be run in parallel, meaning the set-production
task may be run after the other tasks. You can solve this problem with the run-sequence
package.
var runSequence = require('run-sequence');
gulp.task('build', function(callback) {
runSequence('set-production', ['scripts', 'styles', 'otherstuff'], callback);
});
This will run the set-production
task first, then run the scripts
, styles
, and otherstuff
tasks in parallel.
Upvotes: 13