gulp watchify needs two saves to include changes - javascript

Been trying to use watchify for a while now and I have a problem with the saving.
It seems like for every change I make, I need to save two times in order for the changes to be applied in the output.
If I add code in any js-file, the newly added code will only show up if the task runs two times.
My code for the mainScrpits-task
var customOpts = {
entries: ['./app/app.js'],
debug: true
};
var opts = assign({}, watchify.args, customOpts);
var b = watchify(browserify(opts));
gulp.task('mainScripts', bundle);
b.on('update', bundle);
b.on('log', gutil.log);
function bundle() {
console.log('bundle');
return b.bundle()
.on('error', gutil.log.bind(gutil, 'Browserify Error'))
.pipe(source('main.js'))
.pipe(buffer())
.pipe(gulpif(!condition, sourcemaps.init({
loadMaps: true
})))
.pipe(gulpif(!condition, sourcemaps.write('./')))
.pipe(gulp.dest('./dist/js/'))
.pipe(gulpif(isLocal(), connect.reload()));
}
The "watch"-task
gulp.task('watch', function() {
gulp.watch('app/**/*.js', ['mainScripts']);
});

Both watchify and gulp.watch are looking for changes on your files and that causes race conditions on the creation of the bundle.
Your watch task should just start your mainScripts task:
gulp.task('watch', function() {
gulp.start('mainScripts');
});

Related

"Task never defined" error going from Gulp 3 to Gulp 4

I'm trying to convert my gulp 3 file to gulp 4 after upgrading to Node v12, and I'm still erroring out even after reading tutorials/examples. I'm getting the AssertionError [ERR_ASSERTION]: Task never defined: sass error
My gulpfile.js file:
const gulp = require('gulp');
const browserSync = require('browser-sync').create();
const sass = require('gulp-sass');
// Compile Sass & Inject Into Browser
gulp.task('sass', gulp.series('sass'), function() {
return gulp.src(['node_modules/bootstrap/scss/bootstrap.scss', 'src/scss/*.scss'])
.pipe(sass())
.pipe(gulp.dest("src/css"))
.pipe(browserSync.stream());
});
// Move JS Files to src/js
gulp.task('js', gulp.series(['js']), function() {
return gulp.src(['node_modules/bootstrap/dist/js/bootstrap.min.js', 'node_modules/jquery/dist/jquery.min.js','node_modules/popper.js/dist/umd/popper.min.js'])
.pipe(gulp.dest("src/js"))
.pipe(browserSync.stream());
});
// Watch Sass & Serve
gulp.task('serve', gulp.series(['sass']), function() {
browserSync.init({
server: "./src"
});
gulp.watch(['node_modules/bootstrap/scss/bootstrap.scss', 'src/scss/*.scss'], gulp.series('sass'));
gulp.watch("src/*.html").on('change', browserSync.reload);
});
// Move Fonts to src/fonts
gulp.task('fonts', gulp.series(['fonts']), function() {
return gulp.src('node_modules/font-awesome/fonts/*')
.pipe(gulp.dest('src/fonts'))
})
// Move Font Awesome CSS to src/css
gulp.task('fa', gulp.series(['fa']), function() {
return gulp.src('node_modules/font-awesome/css/font-awesome.min.css')
.pipe(gulp.dest('src/css'))
})
gulp.task('default', ['js','serve', 'fa', 'fonts']);
Any help is greatly appreciated, thanks!
To start this form is incorrect:
gulp.task('sass', gulp.series('sass'), function() {
That calls the 'sass' at the beginning of the 'sass' task itself. It would presumably cause an infinite loop. I suspect it is the cause of your error because you are calling the 'sass' task before it has been completely defined.
gulp.task takes only two arguments: the name and one function, so this is correct:
gulp.task('sass', function() {
so make that change to all your tasks except:
gulp.task('serve', gulp.series(['sass']), function() {
where you might want to run the 'sass' task before starting the server. But you can still only have two arguments to gulp.task so try
gulp.task('serve', gulp.series('sass', function() {
Finally, this line
gulp.task('default', ['js','serve', 'fa', 'fonts']);
needs a gulp.series to work properly in gulp v4 so try
gulp.task('default', gulp.series('js','serve', 'fa', 'fonts'));
Once you make all those changes, see if you get any other errors.

Convert gulp watch in gulp#3.9.1 to gulp#4

We are switching from gulp#3.9.1 to gulp#4 and are having trouble switching over. When we run gulp watch, we are getting the following errors and trying to figure out how to resolve it.
What is the proper way to convert the gulp watch task to work with gulp#4?
Error message
AssertionError [ERR_ASSERTION]: Task never defined: minify-css
Command: gulp watch
This should run minify-js then minify-css in order
minify-js should run after clean-scripts has completed successfully
minify-css should run after clean-css has completed successfully
Current tasks.
var gulp = require('gulp'),
cssmin = require('gulp-clean-css'),
clean = require('gulp-clean'),
uglify = require('gulp-uglify');
var src = {
js: 'js/some-dir/**/*.js',
css: 'css/some-dir/**/*.css'
};
var dest = {
js: 'js/dest/some-dir/**/*.js',
css: 'css/dest/some-dir/**/*.css'
};
gulp.task('clean-css', function() {
return gulp.src(dest.css)
.pipe(clean({read:false, force: true});
});
gulp.task('minify-css', ['clean-css'], function() {
gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
});
gulp.task('clean-scripts', function() {
return gulp.src(dest.js)
.pipe(clean({read:false, force: true});
});
gulp.task('minify-js', ['clean-scripts'], function() {
gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
});
gulp.task('watch', ['minify-js', 'minify-css'], function() {
gulp.watch(src.js, ['minify-js']);
gulp.watch(src.css, ['minify-css']);
});
We tried doing this, but it resulted in the error message
gulp.task('watch', gulp.series('minify-js', 'minify-css', function() {
gulp.watch(src.js, ['minify-js']);
gulp.watch(src.css, ['minify-css']);
}));
gulp.task('minify-css', gulp.series('clean-css', function() {
return gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
}));
gulp.task('minify-js', gulp.series('clean-scripts', function() {
return gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
}));
gulp.task('watch', gulp.series('minify-js', 'minify-css', function() {
gulp.watch(src.js, gulp.series('minify-js'));
gulp.watch(src.css, gulp.series('minify-css'));
}));
As #Abdaylan suggested, I also advocate switching to functions. Nevertheless, so you can see where your code was wrong, I have fixed it here. Gulp 4 does not use this syntax:
gulp.task('someTask', ['task1', 'task2'], function () {}); // gulp 3
Gulp 4:
gulp.task('someTask', gulp.series('task1', 'task2', function () {})); // gulp 4 with string tasks
or gulp.parallel. So you can use your gulp.task syntax (rather than named functions) if you modify them to use the signatures that gulp 4 supports as I did in your modified code at the top of this answer.
Gulp 4 with named functions:
gulp.task(someTask, gulp.series(task1, task2, function () {})); // gulp 4 with named functions
So with named functions, the tasks are not referred to as strings.
See also task never defined for other potential problems when migrating from gulp3 to gulp4 with the same error message.
I would recommend converting your minify-js, minify-css, clean-scripts and clean-css tasks to functions:
var dest = {
js: 'js/dest/some-dir/**/*.js',
css: 'css/dest/some-dir/**/*.css'
};
function cleanCss() {
return gulp.src(dest.css)
.pipe(clean({read:false, force: true});
});
function minifyCss() {
return gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
});
function cleanScripts() {
return gulp.src(dest.js)
.pipe(clean({read:false, force: true});
});
function minifyJs() {
return gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
});
var minifyJsAndClean = gulp.series(minifyJs, cleanScripts);
var minifyCssAndClean = gulp.series(minifyCss, cleanCss);
var watchers = function (done) {
gulp.watch(src.js, minifyJs);
gulp.watch(src.css, minifyCss);
done();
}
gulp.task('watch', gulp.series(minifyJsAndClean, minifyCssAndClean, watchers));
I just ran into this a couple days ago myself. What worked for me was to run each task in its own gulp.watch() with the gulp.series() on the watch task call instead of the watch task itself. For example:
gulp.task('watch', function() {
gulp.watch(src.js, gulp.series('minify-js'));
gulp.watch(src.css, gulp.series('minify-css'));
});

Gulp-sourcemaps returning only returning `source` js file

My sourcemaps are only returning the source value no matter what.
Broswerify.js
// add custom browserify options here
var customOpts = {
entries: ['./frontend/js/app.js'],
debug: true
};
var opts = assign({}, watchify.args, customOpts);
var b = watchify(browserify(opts));
b.transform(require("jadeify"), { compileDebug: true, pretty: false });
// add transformations here
// i.e. b.transform(coffeeify);
gulp.task('browserify', bundle); // so you can run `gulp js` to build the file
b.on('update', bundle); // on any dep update, runs the bundler
b.on('log', gutil.log); // output build logs to terminal
function bundle() {
return b.bundle()
// log errors if they happen
.on('error', gutil.log.bind(gutil, 'Browserify Error'))
.pipe(source('main.js'))
// optional, remove if you don't need to buffer file contents
.pipe(buffer())
// optional, remove if you dont want sourcemaps
.pipe(sourcemaps.init({loadMaps: true})) // loads map from browserify file
// Add transformation tasks to the pipeline here.
.pipe(sourcemaps.write('./')) // writes .map file
.pipe(gulp.dest('./public/js'))
.on('end', function () {
browserSync.reload();
});
}
main.js.map
{"version":3,"sources":["/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js","/main.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;
This of course means that all files are referenced as main.js which is less then helpful :(
I am also using browser-sync, but I don't believe this has any effect on sourcemaps.
I was using gulp-sourcemaps v2.3.0
Upgraded to v2.6.0 and now its working. I thank you sir

My gulp task to "concat" and "dest" my .css file, is only running if I run 2 times

The concatenation and destination to my public/assets/css is only working if i run 2 times the task. Even if I run just the app.css (npm run dev app.css), only work if I run twice.
const gulp = require('gulp')
const htmlmin = require('gulp-htmlmin')
const uglify = require('gulp-uglify')
const uglifycss = require('gulp-uglifycss')
const concat = require('gulp-concat')
const babel = require('gulp-babel')
const sass = require('gulp-sass')
gulp.task('app', ['app.html', 'app.sass', 'app.js', 'app.assets', 'app.css'])
gulp.task('app.html', function(){
gulp.src(['app/**/*.html'])
.pipe(htmlmin({ collapseWhitespace: true, removeComments: true}))
.pipe(gulp.dest('public'))
})
gulp.task('app.sass', function () {
gulp.src(['sass/main.scss'])
.pipe(sass.sync().on('error', sass.logError))
.pipe(gulp.dest('app/css'))
});
gulp.task('app.css', function(){
gulp.src(['app/**/*.css'])
.pipe(uglifycss({ "uglyComments": true}))
.pipe(concat('app.min.css'))
.pipe(gulp.dest('public/assets/css'))
})
gulp.task('app.js', function(){
gulp.src(['app/**/*.js'])
.pipe(babel({ presets: ['es2015'] }))
.pipe(uglify())
.pipe(concat('app.min.js'))
.pipe(gulp.dest('public/assets/js'))
})
gulp.task('app.assets', function(){
gulp.src(['assets/**/*.*'])
.pipe(gulp.dest('public/assets'))
})
For gulp to respect the order of the task dependencies you defined, you need to tell it when the task is done.
To do so, you need to return a stream, a promise, or call the task function callback parameter.
Since your tasks are pretty basic, just returning the stream should be enough.
gulp.task('app.sass', function () {
return gulp.src(['sass/main.scss']) // notice the return here
.pipe(sass.sync().on('error', sass.logError))
.pipe(gulp.dest('app/css'));
});
// make the sass task a dependency of the CSS task
gulp.task('app.css', ['app.sass'], function(){
return gulp.src(['app/**/*.css']) // notice the return here
.pipe(uglifycss({ "uglyComments": true}))
.pipe(concat('app.min.css'))
.pipe(gulp.dest('public/assets/css'));
});
Now you don't need the app.sass since it will run before app.css.
gulp.task('app', ['app.html', 'app.js', 'app.assets', 'app.css'])
I think that your tasks should be waiting for a result from the previous task. You can't just run several tasks in one time.
Try with gulp-sequence plugin. Install gulp-sequence and add the following line on the top of your gulpfile.js:
const gulpSequence = require('gulp-sequence')
Replace your current 'app' task by:
gulp.task('app', gulpSequence('app.html', 'app.sass', 'app.js', 'app.assets', 'app.css'))

Using Jade features with gulp-changed?

When I make changes to .jade files I want to Gulp task run only for that file, not for all files. For that I'm using gulp-changed. It's working fine, until I make changes to files that affect to global layout, eg _header.jade, _layout.jade. When I make changes to that files nothing happens. All my layout files have _ before title. How can I solve this issue?
Here is my gulpfile some lines
gulp.task('jade', function() {
return gulp.src('dev/templates/**/!(_)*.jade')
.pipe(plumber({
errorHandler: onError
}))
.pipe(changed('public', {extension: '.html'}))
.pipe(jade({
pretty: true,
}))
.pipe(gulp.dest('public'))
.pipe(browserSync.reload({
stream: true
}));
});
gulp.task('watch', function() {
gulp.watch('dev/templates/**/*.jade', gulp.series('jade'));
});
First thing I would do is to refactor out your jade compilation task into a separate function. That allows you to parameterize your jade compilation so that you can run it on one or more files of your choice:
function compileJade(files) {
return gulp.src(files, {base:'dev/templates'})
.pipe(plumber({
errorHandler: onError
}))
.pipe(jade({
pretty: true,
}))
.pipe(gulp.dest('public'))
.pipe(browserSync.reload({
stream: true
}));
}
Your existing jade task now simply calls that function:
gulp.task('jade', function() {
return compileJade('dev/templates/**/!(_)*.jade');
});
If a changed file is a partial (starts with _) we need to be able to determine which other files are affected by that change. This is facilitated by the jade-inheritance library:
var JadeInheritance = require('jade-inheritance');
var path = require('path');
function isPartial(file) {
return path.basename(file).match(/^_.*/);
}
function findAffectedFiles(changedFile) {
return new JadeInheritance(changedFile, 'dev/templates', {basedir: 'dev/templates'})
.files
.filter(function(file) { return !isPartial(file); })
.map(function(file) { return 'dev/templates/' + file; })
}
Finally whenever a file changes we call the compileJade function for the affected files only:
gulp.task('watch', function() {
gulp.watch('dev/templates/**/*.jade').on('change', function(changedFile) {
return compileJade(isPartial(changedFile) ? findAffectedFiles(changedFile) : changedFile);
});
});

Categories