I upgraded from Gulp 3.x.x to Gulp 4.0.2 and began editing my gulpfile to make it compatible, but I'm stuck on this error I get when I try to run gulp:
AssertionError [ERR_ASSERTION]: Task never defined: browserSync.reload
Here is what I believe is the relevant portion of my gulpfile:
gulp.task('browserSync', function() {
browserSync({
server: {
baseDir: 'app'
},
browser: 'Chrome'
})
})
gulp.task('sass', function() {
return gulp.src('app/styles/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs
.pipe(sass().on('error', sass.logError)) // Passes it through a gulp-sass, log errors to console
.pipe(gulp.dest('app/styles')) // Outputs it in the css folder
.pipe(browserSync.reload({ // Reloading with Browser Sync
stream: true
}));
})
// Watchers
gulp.task('watch', function() {
gulp.watch('app/styles/**/*.scss', gulp.series('sass'));
gulp.watch('app/*.html', gulp.series('browserSync.reload'));
gulp.watch('app/js/**/*.js', gulp.series('browserSync.reload'));
})
I'm using node version 11.15.0. Later versions were giving me problems.
Your immediate error is a result of these two lines:
gulp.watch('app/*.html', gulp.series('browserSync.reload'));
gulp.watch('app/js/**/*.js', gulp.series('browserSync.reload'));
Simply remove the quotes around the browserSync.reload calls:
gulp.watch('app/*.html', gulp.series(browserSync.reload));
gulp.watch('app/js/**/*.js', gulp.series(browserSync.reload));
If those calls were calls to tasks then it would be correct to put them into quotes. But your calls are not to tasks but to your const browserSync = require('browser-sync) package.
So it is confusing and will probably lead to errors to use the same identifier - browserSync for both your package require name and the task name as it appears you did.
As can be seen here:
gulp.task('browserSync', function() {
browserSync({
server: {
baseDir: 'app'
},
browser: 'Chrome'
})
})
The first use of browserSync is as a task name. The second, in the function body, is a reference to the package name. And the second is ultimately the one used in your watch tasks and would not be quoted there because it is not a task name. So using browserSync both ways is definitely confusing - just pick a different name for one like:
gulp.task('bSync', function() {
browserSync.init({......
Also note the init added to the above code. You will need it.
Related
I am using Gulp 4 to compile my code from TypeScript to JavaScript and to build and serve the app.
I've come across one problem that I cannot solve.
I'd like to run the build, copy-html and copy-css tasks before some file gets changed.
According to Gulp documentation I just need to provide a config object with ignoreInitial set to false, but it doesn't work.
I've tried to call the three tasks before I initialize browserSync but for it also didn't work for me.
gulp.task("serve", function() {
// TODO Make a build before first serve
browserSync.init({
server: {
baseDir: "./dist/"
}
});
gulp
.watch(["src/**/*.ts", "src/**/*.html", "src/**/*.css"], {
ignoreInitial: false
})
.on(
"change",
gulp.series(
gulp.parallel("copy-html", "copy-css"),
build,
browserSync.reload
)
);
});
Instead of using calling .on() on the returned chokidar interface, add your tasks to the watch command.
gulp
.watch(
["src/**/*.ts", "src/**/*.html", "src/**/*.css"],
{ ignoreInitial: false },
gulp.series(
gulp.parallel("copy-html", "copy-css"),
build,
browserSync.reload
)
)
);
I am trying to convert my sass to compressed-css and javascript to uglified-js. And watch both scss and js changes
my code is working but when I tried saving a js file, it goes into a unstoppable loop.
Here is my code:
var gulp = require('gulp');
var sass = require('gulp-sass');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
gulp.task('sass', function(done){
gulp.src('public/sass/**/*.scss')
.pipe(sass({outputStyle: 'compressed'})) // Using gulp-sass
.pipe(gulp.dest('public/stylesheets'))
done();
});
gulp.task('scripts', function(done){
gulp.src('public/javascripts/**/*.js')
.pipe(concat('scripts.js'))
.pipe(uglify())
.pipe(gulp.dest('public/javascripts'))
done();
});
gulp.task('watch', function(){
//I made .scss and .js into an array so they will both be watched
gulp.watch(['public/sass/**/*.scss', 'public/javascripts/**/*.js' ], gulp.series('sass', 'scripts', function(done) {
done();
}))
})
Now when I run gulp watch it is working but then when I save a js file, I goes into a saving loop, It's saves and saves and saves nonstop.
I have made scss work with this code
gulp.task('watch', function(){
gulp.watch('public/sass/**/*.scss', gulp.series('sass', 'scripts', function(done) {
done();
}))
})
But I have no idea how I can make .js files be watched.
I searched google for possible answer but only find the older version solution. Is there a way I can do this with gulp4?
I also tried gulp.parallel but it still looped
Please help. Thanks
Your original code:
gulp.task('watch', function(){
//I made .scss and .js into an array so they will both be watched
gulp.watch(['public/sass/**/*.scss', 'public/javascripts/**/*.js' ], gulp.series('sass', 'scripts', function(done) {
done();
}))
})
should be
gulp.task('watch', function(done){
// added done above too
gulp.watch('public/sass/**/*.scss', gulp.series('sass') )
gulp.watch('public/javascripts/**/*.js', gulp.series('scripts') )
done();
})
Your code triggers both 'sass' and 'scripts' tasks when either a scss or js file is modified, which is wasteful (for example, the 'sass' task will start when a js file is altered but not actually do anything with that js file but will needlessly run the sass re-compilation although no scss file changed).
I solved this by doing this:
gulp.task('watch', function(){
//I added the src folder instead of the glob **(two asterisk)
gulp.watch(['public/sass/**/*.scss', 'public/javascripts/src/*.js'], gulp.series('sass', 'scripts', function(done) {
done();
}))
})
I don't know why this happened but it's working now
Link to Github Repo: https://github.com/janschloss/boilerplate
My problem is that only scss changes get recognized by BrowserSync in Gulp (no html or js or /img changes). I guess that is because scss changes are streamed directly. Weirdly I had one build which recognized html and img changes though I can't find that again.
Does someone see the mistake?
"use strict";
// Define packages
var gulp = require('gulp'),
sass = require('gulp-sass'),
clean = require('gulp-clean'),
sourcemaps = require('gulp-sourcemaps'),
autoprefixer = require('gulp-autoprefixer'),
plumber = require('gulp-plumber'),
imagemin = require('gulp-imagemin'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
strip = require('gulp-strip-comments'),
browserSync = require('browser-sync');
// Define file paths
var scssSrc = 'src/scss/**/*.scss',
jsSrc = 'src/js/*.js',
htmlSrc = 'src/*.html',
imgSrc = 'src/img/*';
// BrowserSync config
gulp.task('browserSyncInit', function() {
browserSync.init({
server: {
baseDir: 'dist'
}
});
gulp.watch('./dist/*').on('change', browserSync.reload);
});
// Concat scss files, compile compressed to css, prefix css, strip comments and create sourcemap
gulp.task('sass', function() {
return gulp.src(scssSrc)
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(concat('main.min.scss'))
.pipe(sass({outputStyle: 'compressed'}))
.pipe(autoprefixer())
.pipe(strip.text())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist/css'))
.pipe(browserSync.reload({
stream: true
}));
});
// Concatenate, uglify, strip comments and create sourcemap for js files
gulp.task('js', function() {
return gulp.src(jsSrc)
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(concat('main.min.js'))
.pipe(uglify())
.pipe(strip())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist/js'));
});
// Image optimization
gulp.task('img', function () {
return gulp.src(imgSrc)
.pipe(imagemin({
progressive: true
}))
.pipe(gulp.dest('dist/img'));
});
// Clean task
gulp.task('clean', function() {
return gulp.src('dist')
.pipe(clean());
});
// Copy html
gulp.task('copy', function() {
return gulp.src(htmlSrc)
.pipe(gulp.dest('dist/'));
});
// Default Task
gulp.task('default', ['clean', 'copy', 'sass', 'js', 'img', 'browserSyncInit'], function () { //todo asynchronous
gulp.watch(scssSrc, ['sass']);
gulp.watch(jsSrc, ['js']);
gulp.watch(imgSrc, ['img']);
gulp.watch(htmlSrc, ['copy']);
});
I think
gulp.watch('./dist/*').on('change', browserSync.reload);
is the relevant line. Is there anything wrong with my path?
My relevant folder structure looks like:
gulpfile.js
src
dist
Changes are made in src and copied over to dist on runtime with gulp.
Thanks!
I can't explain it. But when I remove your watch call from the browserSyncInit task and put it in the callback for the default task along side the other watches, everything works fine.
Relevant pieces of code:
// BrowserSync config
gulp.task('browserSyncInit', function() {
browserSync.init({
server: {
baseDir: 'dist'
}
});
});
// Default Task
gulp.task('default', ['clean', 'copy', 'sass', 'js', 'img', 'browserSyncInit'], function () { //todo asynchronous
gulp.watch(scssSrc, ['sass']);
gulp.watch(jsSrc, ['js']);
gulp.watch(imgSrc, ['img']);
gulp.watch(htmlSrc, ['copy']);
gulp.watch('./dist/**/*').on('change', function () {
console.log("Watch hit");
browserSync.reload();
});
});
Is this ideal at all for your gulp file? I can kind of understand the thinking of having the watch originally triggered inside the other task.
Very weird thing I noticed; Sometimes the DIST watch would take and all the other watches wouldn't. As if there is a race condition happening on which ones get registered and the others get overwritten. When they were separated like you had them originally, either SRC watches worked or DIST watches worked. I could edit files in DIST directly when the DIST watch was working and trigger reload.
Keeping all the watches together in that CB function works for me using your github project.
I also noticed another unrelated issue. Rerunning your gulp file required me to rm -rf dist first other wise I got errors.
I think the problem is with the glob: './dist/*' - it will only watch the contents of dist. I think you want './dist/**/*' to watch the folder and all subfolders.
I have a Gulp task that lints Javascript files before injecting them into a HTML page. I'd like the files not to be injected if a linting error is found. So if an error appears in the first task, cancel all subsequent tasks.
The caveat is that this task is run by gulp.watch and I'd like the watch to continue to monitor the files and inject them if the linting errors are resolved.
Is this possible in gulp? Plugins are acceptable.
Gulpfile below:
var gulp = require('gulp');
var runSequence = require('run-sequence');
//(plugin declarations removed for brevity)
gulp.task('eslint', function() {
return gulp.src(config.lint)
.pipe($.cached('eslint'))
.pipe($.eslint())
.on('error', $.gutil.log)
.pipe($.eslint.format());
});
gulp.task('inject:resources', function() {
return gulp.src(config.src.templates)
.pipe(
$.inject(gulp.src(config.dist.scripts + '/all*.js',
{read: false}),
{
ignorePath: config.dist.public,
addRootSlash: false,
name: 'scripts'
}
))
.pipe(gulp.dest(config.dist.public));
});
gulp.task('watch:js', function(callback) {
runSequence('eslint', 'inject:resources');
});
gulp.task('watch', function() {
gulp.watch(config.src.scripts, ['watch:js']);
});
First you need to make eslint fail when any of your files produces an error. You can do that by placing eslint.failAfterError() at the end of your stream:
gulp.task('eslint', function() {
return gulp.src(config.lint)
.pipe($.cached('eslint'))
.pipe($.eslint())
.on('error', $.gutil.log)
.pipe($.eslint.format())
.pipe($.eslint.failAfterError());
});
When your eslint task fails the subsequent inject:resources task will not be executed by runSequence.
Next you need to make the callback in your watch:js task available to runSequence, otherwise gulp will not notice when watch:js has finished (and since you can't run the same task in parallel with itself this would effectively prevent watch:js from being started again):
gulp.task('watch:js', function(callback) {
runSequence('eslint', 'inject:resources', callback);
});
The only downside to this is that the above will produce an ugly stack trace that doesn't really provide any useful additional info. If you want to prevent that you can just "swallow" the error that is being passed up the callback chain like this:
gulp.task('watch:js', function(callback) {
runSequence('eslint', 'inject:resources', function(err) {
callback();
});
});
I do not know why those tasks for live reloading just disappear after the last Ionic Update I did. Now I am trying to fix this issue but still wondering why is not working. I am following this guide here and still can not see what is the error I have.
See some part of my gulpfile.js
var paths = {
sass: ['/scss/**/*.scss'],
js: ['www/js/*.js', 'www/js/**/*.js', '!www/js/lib.min.js', '!www/js/code.min.js']
};
gulp.task('compress-lib', function() {
gulp.src([
'./www/lib/ionic/js/ionic.bundle.min.js'
])
.pipe(concat('lib.min.js'))
.pipe(gulp.dest('./www/js'))
});
gulp.task('compress-js', function() {
gulp.src([
'./www/js/app.js',
'./www/js/lines/controller.js',
'./www/js/lines/service.js'
])
.pipe(ngAnnotate())
.pipe(concat('code.min.js'))
.pipe(gulp.dest('./www/js'))
});
// JSHint task
gulp.task('lint', function() {
gulp.src(paths.js)
.pipe(jscs())
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
gulp.task('sass', function(done) {
gulp.src('./scss/ionic.app.scss')
.pipe(sass({onError: function(e) { console.log(e); } }))
.pipe(autoprefixer('last 2 versions', 'Chrome', 'ios_saf','Android'))
.pipe(gulp.dest('./www/css/'))
.pipe(minifyCss({
keepSpecialComments: 0
}))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'))
.on('end', done);
});
gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.js, ['lint', 'compress-js']);
});
every time I do ctrl + s on a file, in this case www/js/lines/controller.js, on the console you can see something like:
[14:41:11] Starting 'lint'...
[14:41:11] Finished 'lint' after 17 ms
[14:41:11] Starting 'compress-js'...
[14:41:11] Finished 'compress-js' after 5.31 ms
JS changed: www/js/lines/controller.js
JS changed: www/js/code.min.js
which means that there are some tasks working properly, but if I want to see those changes on the view, I have to go to the console and type gulp, do you have an idea why the app is not just reloading after ctrl + s ?
UPDATE
This is what I am trying to implement (you can see it on the link I pasted above):
"The watch task is used to run tasks as we make changes to our files. As you write code and modify your files, the gulp.watch() method will listen for changes and automatically run our tasks again so we don't have to continuously jump back to our command-line and run the gulp command each time"
I know this is going around the problem but use live-server instead of live reload and see if that works. Because I have had a lot of problems with live-reload in the past too.
npm install live-server
then:
live-server
NOTE: Make sure you are in the directory of your project when typing the command above.