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.
Related
I've attempted to update the gulpfile below to Gulp v4 from v3 but am still getting an error: AssertionError [ERR_ASSERTION]: Task never defined: client
Not sure what I am missing but realise that the functions may not be written correctly. The tasks in series are correct I believe: gulp.task('build', gulp.series('client', 'sass')); for example.
// gulpfile.js
var gulp = require('gulp'),
concat = require('gulp-concat'),
browserify = require('gulp-browserify'),
rename = require('gulp-rename'),
nodemon = require('gulp-nodemon'),
sass = require('gulp-sass');
gulp.task('build', gulp.series('client', 'sass'));
gulp.task('watch', gulp.series('client-watch', 'sass-watch'));
gulp.task('server', function () {
nodemon({
script: 'server/index',
ext: 'js json'
});
});
gulp.task('client', function () {
gulp.src('client/js/main.js')
.pipe(browserify({
transform: ['hbsfy'],
extensions: ['.hbs']
}))
.pipe(rename('hearthclone.js'))
.pipe(gulp.dest('./client/build'));
});
gulp.task('client-watch', function () {
gulp.watch('client/js/**/*.js', ['client']);
});
gulp.task('sass', function () {
gulp.src('client/**/*.scss')
.pipe(sass())
.pipe(concat('style.css'))
.pipe(gulp.dest('client/assets/css'));
});
gulp.task('sass-watch', function () {
gulp.watch('client/**/*.scss', ['sass']);
});
gulp.task('default', gulp.series('build', 'server', 'watch'));
When you use the gulp.task form of defining tasks (rather that as functions) then you cannot refer to those tasknames until after they have been declared. That would be a forward reference (see below). So just put your
gulp.task('build', gulp.series('client', 'sass'));
gulp.task('watch', gulp.series('client-watch', 'sass-watch'));
after all those tasks have been defined. I recommend right before the default task line.
See https://gulpjs.com/docs/en/api/series#forward-references
Forward references
A forward reference is when you compose tasks, using string
references, that haven't been registered yet. This was a common
practice in older versions, but this feature was removed to achieve
faster task runtime and promote the use of named functions.
In newer versions, you'll get an error, with the message "Task never
defined", if you try to use forward references. You may experience
this when trying to use exports for your task registration and
composing tasks by string. In this situation, use named functions
instead of string references.
I am super new to using Node.js, NPM and all these modern tools for better productivity and workflow.
So here are the details:
Node version - v8.10.0
Gulp CLI version - 2.0.1
Gulp Local version - 3.9.1
NPM version - 5.6.0
Windows 7
Node.js installed in D:/ProgramFiles
I've tried using gulp and it does work wonderfully with this script
var gulp = require('gulp'),
watch = require('gulp-watch');
gulp.task('default',function(){
console.log('Gulp task created');
});
gulp.task('html' , function() {
console.log('Something useful here');
});
gulp.task('watch', function() {
watch('/app/index.html', function() {
gulp.start('html');
});
});
So typing gulp does respond with the default task message. Typing gulp html does respond too with a console message. However, when i type gulp watch, it does work with following output.
Starting 'watch'...
Finished 'watch' after 7.99 ms
But whenever i make changes and save the index file, the cmd doesn't update. I've tried using Git Bash and other terminals. I've even installed previous node versions and tried solving this issue using those but no luck so far.
I tried editing the dependencies to an older version but that doesn't work too.
If anyone of you can help, I'll be thankful.
Updated with callback method to end process for a graceful exit and not use CTRL-C.
gulp.task('watch',function(){
gulp.watch('./data/index.html', function(){
gulp.start(['someOtherGulpTask']);
});
});
gulp.task('someOtherGulpTask', function () {
gulp.src('./test/sometest.js')
.pipe(gulpmocha(),setTimeout(function() {
cb();
}, 5000))
});
function cb(){
process.exit(1);
}
Original answer below
The order of execution of gulp tasks are -
the default task gets executed and then the subsequent ones unless the task
to be executed is specifically mentioned in the cmdline call to gulp as you
have mentioned - "gulp watch".
you can specify the order in the beginning of the gulpfile like
gulp.task('default', ['watch']);
or, you can start a task explicitly like so,
gulp.task('default',function(done){
console.log('Gulp task created');
gulp.start('watch');
done();
});
done is the callback that allows your waiting task to complete which is missing in your gulp file. Below is the complete gulp file that you can use to execute the watch task as you require.
var gulp = require('gulp'),
watch = require('gulp-watch');
gulp.task('default',function(done){
console.log('Gulp task created');
gulp.start('watch');
done();
});
gulp.task('html' , function() {
console.log('Something useful here');
});
gulp.task('watch', function() {
watch('./data/index.html', function() {
console.log('Some changes done');
});
});
gulp.task('watch', function () {
gulp.watch('./data/index.html', ['html']);
});
Avoid gulp.start, it is not documented or recommended.
I am using gulp to run a developer web server and I want the following tasks to happen when a change occurs to a javascript file:
Lint javascript
if there are no errors, copy files to .tmp/
reload webpage
I've seen in other examples to use jshint.reporter('fail') as shown in the code below, to stop the rest of the pipeline.
var jshint = require('gulp-jshint'),
watch = require('gulp-watch');
watch('resources/js/src/**/*.js', function() {
util.log('Changes to js source files detected');
}).pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'))
.pipe(gulp.dest('.tmp/js/src/'))
.pipe(connect.reload());
However when I do this it appears to always stop regardless of whether or not the lint was a success. So, how can I end the pipeline after a failed linting?
Not sure if this is the best solution, but it works:
var map = require('map-stream');
...
var copyAndReload = map(function (file, cb) {
if (file.jshint.success) {
gulp.src('resources/js/src/**/*.js')
.pipe(gulp.dest('.tmp/js/src/'))
.pipe(connect.reload());
}
});
watch('resources/js/src/**/*.js', function() {
util.log('Changes to js source files detected');
}).pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(copyAndReload);
what you can do is plugin plumber to exit in case of error
so pipe the plumber in the linting process
.pipe(plumber(_doExit))
here is how you defined _doExit
function _doExit() {
process.exit(1);
}
I am trying eslint with gulp. I have set up a task like this:
gulp.task('lint', function () {
return gulp.src([
'components/myjs.js'
])
// eslint() attaches the lint output to the eslint property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failOnError last.
.pipe(eslint.failOnError());
});
when I run gulp lint
It tells me a lot of errors. Now I am trying to fix them one by one. But I have to re-run gulp lint manually for it to give me an updated report. How do I set it up so that it will automatically re-run every time I update 'components/myjs.js'?
Just add a watch task:
gulp.task('watch', function() {
gulp.watch('components/myjs.js', ['lint']);
});
This way Gulp will track any changes on your 'components/myjs.js' and execute your 'lint' task on any change
If you want further reading:
https://scotch.io/tutorials/automate-your-tasks-easily-with-gulp-js
I have a simple build script that supposedly should pack all my js modules into a single file using browserify. I have the following code ( inspired from http://www.forbeslindesay.co.uk/post/46324645400/standalone-browserify-builds)
function _browserify(srcPath, distPath) {
var browserify = require('browserify');
var b = new browserify();
b.add(srcPath);
b.bundle().pipe(_fs.createWriteStream(distPath));
console.log(' '+ distPath +' built.');
}
But when I run it, I get a completely empty file. Any idea why?
okay, definitely spent waaaay too much of my evening on this, but this turns out to be an async issue. you're most likely getting an error in there somewhere, but grunt is killing off the process before the error callback has a chance to be called. grunt provides a nifty async method on each task's context that you have to use to let grunt know that this is an async task (and therefore needs to wait for everything to be finito). something like...
grunt.registerTask('build', function () {
var done = this.async();
browserify({ debug: true })
.add('./src/main.js')
.bundle()
.on('error', function (err) {
console.log(err);
})
.pipe(fs.createWriteStream('./target/bundle.js')
.on('end', done);
});