I have such a gulp task
gulp.task("js-min", function () {
browserify(config.paths.mainJs)
.transform(reactify)
.bundle()
.pipe(source('tec.min.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify())
.pipe(sourcemaps.write(config.paths.dist))
.pipe(gulp.dest(config.paths.dist));
});
that create the minified version of the application. It runs periodically by the gulp-watch task. The problem I see, is that gulp tells me this task finishes in 30ms, but if I check the file being generated, it takes another 30s to see the actual new file being updated.
How shall I change the gulp task js-min so I know exactly when the file was finished updating in file system.
There are two solutions, and without knowing what browserify package you are using.
If it is promise based, then simply edit your code to return that promise:
gulp.task("js-min", function () {
return browserify(config.paths.mainJs)
If it is not promise-based, then it will have some kind of an onend or done method that takes a callback. In that case, it would be like this:
gulp.task("js-min", function (done) {
browserify(config.paths.mainJs)
.transform(reactify)
.bundle()
.pipe(source('tec.min.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify())
.pipe(sourcemaps.write(config.paths.dist))
.pipe(gulp.dest(config.paths.dist))
// THIS IS THE LINE TO CHANGE
.onfinish(done);
});
Related
I'm new in Gulp and this is my code that just minifies my JS script:
gulp.task('minify-js', function(){
return gulp.src(['assets/js/**/*.js', '!assets/js/**/*.min.js'])
.pipe(uglify())
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('./assets/js'))
});
gulp.task('watch', function(){
//gulp.watch(['sass/**/*.sass'], gulp.series('css-files'));
gulp.watch(['assets/js/**/*.js'], gulp.series('minify-js'));
});
gulp.task('default', gulp.series('watch'));
When I run gulp default and edit any JS file, my task starts looping for no reason and the files keep being minified and merged aswell. Why? It should stop after one execution!
example:
*This code runs perfectly without the watch task
Any help?
Your destination file matches the mask of source files.
So Gulp process the file it just generated themself. And then again, and again.
Update: you've excluded the file in minify-js task, but not excluded in watch task. Set watch argument the same as for minify-js and that should help.
I'm trying to run a set of tasks in series, that is one after the other in Gulp 4.0 however when I add my 3rd task my gulp code breaks.
gulp.task('concat-js', (done) => {
gulp.src([
'app1.js',
'app2.js',
])
.pipe(concat("app.js"))
.pipe(gulp.dest('build'))
done();
});
gulp.task('concat-css', (done) => {
gulp.src([
'.styles1.css',
'.style2.css'
])
.pipe(concat("app.css"))
.pipe(gulp.dest('build'))
done();
});
gulp.task('minify-js', (done) => {
gulp.src('./build/app.js')
.pipe(uglify())
.pipe(gulp.dest('./build/'))
done();
})
//this works & creates /build with the app.js & app.css files
gulp.task('build-production-static-resource', gulp.series('concat-js', 'concat-css',, (done) => {
done();
}));
If I delete the build folder to start all over & try adding another task (minfy-js), my third task fails & the build folder also doesn't get created.
//File not found with singular glob: /Users/user/myapp/build/app.js
gulp.task('build-production-static-resource', gulp.series('concat-js', 'concat-css', 'minify-js', (done) => {
done();
}));
The way you're signalling async completion of your tasks is wrong. Read this answer for an overview of the different ways in which you can signal async completion in gulp.
Basically all the streams that you create via gulp.src() are asynchronous. That means you create the stream and your code immediately returns. However the actual processing of the stream starts only after you exit the task function. In order for gulp to know that you're using a stream and that it has to wait for the stream to finish processing, you need to return the stream from your task.
You're doing something else entirely. You're invoking a callback function done which is another way to signal asynchronous task completion to gulp. However that's the completely wrong way in this case, because when you invoke the callback function done the stream you created hasn't even started to process.
That means gulp thinks your concat-js task has finished, although the code inside your task hasn't even really started running. So when the minify-js task runs your ./build/app.js file hasn't been created yet. Boom. Error.
To fix this always return the streams from your tasks:
gulp.task('concat-js', () => {
return gulp.src([
'app1.js',
'app2.js',
])
.pipe(concat("app.js"))
.pipe(gulp.dest('build'))
});
gulp.task('concat-css', () => {
return gulp.src([
'.styles1.css',
'.style2.css'
])
.pipe(concat("app.css"))
.pipe(gulp.dest('build'))
});
gulp.task('minify-js', () => {
return gulp.src('./build/app.js')
.pipe(uglify())
.pipe(gulp.dest('./build/'))
})
gulp.task('build-production-static-resource', gulp.series(
'concat-js', 'concat-css', 'minify-js'
));
I'm using the following code because grabbing the whole js folder won't honor file sequence. So I select file by file, but it won't produce the site.min.js file even though no error is given.
gulp.task("minjs", function () {
gulp.src([
'js/site.js',
'js/directives/navbar.js',
'js/directives/Select.Lang.js'
])
.pipe(concat('site.min.js'))
.pipe(uglify())
.pipe(gulp.dest("wwwroot/js/"));
});
Updated:
No, it's not the return. I tried that too. I also searched trough my PC if a file was generated, but there's no file and the weirdest thing is that the gulp task shows no error.
Notice the return statement:
gulp.task("minjs", function () {
return gulp.src([
'js/site.js',
'js/directives/navbar.js',
'js/directives/Select.Lang.js'
])
.pipe(concat('site.min.js'))
.pipe(uglify())
.pipe(gulp.dest("wwwroot/js/"));
});
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?)
THE RIGHT WAY
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/'));
});
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.
Please find the content of the gulpfile.js as below.
The task uglify depends on the task jshint. Currently when I run gulp, both the tasks get executed, irrespective of the outcome of the jshint task. I don't want the uglify task to get executed when there are 'jshint' error(s).
In other words, when ever there are dependent tasks, I don't want the subsequent tasks to get executed, if there are error detected by the preceding task.
Is it possible in gulp?
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
gulp.task('jshint', function () {
return gulp.src(['assets/js/**/*.js'])
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('jshint-stylish'));
});
gulp.task('uglify', ['jshint'], function() {
return gulp.src('assets/js/**/*.js')
.pipe(uglify())
.pipe(gulp.dest('assets-min/js/'));
});
gulp.task('default', ['jshint', 'uglify']);
Please refer the below console output - not desired. Though there had been jshint error, the uglify task ran successfully.
I have also created a GitHub repository with the boilerplate code for the above mentioned.
Please find the same at #sarbbottam/gulp-workflow.
Console out of the undesired workflow
Console out of the expected workflow
For JSHint, there is a built-in reporter for this purpose, fail. If an error occurs, it will stop your gulp process.
You just have to redefine your task like :
gulp.task('jshint', function () {
return gulp.src(['assets/js/**/*.js'])
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('jshint-stylish'))
.pipe(jshint.reporter('fail'))
})
With other tasks, you can add an error callback on it and exit the process to prevent subsequent tasks to run.
Here is an example with ngmin (cause uglify is hard to break, but it will be the same) :
function handleError (err) {
console.log(err.toString())
process.exit(-1)
}
gulp.task('min', function () {
return gulp.src(['assets/js/**/*.js'])
.pipe(ngmin())
.on('error', handleError)
})
To complement Aperçu's answer, if you don't want gulp to just exit (because you have watcher running) then you can do the following:
gulp.task('min', function(done) {
return gulp.src(['assets/js/**/*.js'])
.pipe(ngmin())
.on('error', done);
});
This will prevent the next task that depends on this one to run but your watchers will still be running.