dandaka
dandaka

Reputation: 869

gulp-watch and LiveReload, reloads too early

I have set up gulp-watch and LiveReload. It works somehow, but most of the time wrong. It feels like LiveReload is emitting reload event faster, than browser should reload files. I could explain it like this:

  1. Some files has changed in my src directory
  2. It starts to compile
  3. While it is still compiling, browser reloads the page
  4. Sometimes page is already new and correct. Most of the time it is old. Sometimes its only part of the page.
  5. Hit reload and everything is fine.

I think I made some mistake, while integrating gulp-watch and LiveReload. Could you help me finding one?

Here is my gulpfile.js:

var gulp = require('gulp');
var jade = require('gulp-jade');
var sass = require('gulp-sass');
var watch = require('gulp-watch');
var connect = require('gulp-connect');
var favicons = require('gulp-favicons');
var ga = require('gulp-ga');
var postcss      = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var responsive = require('gulp-responsive');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var print = require('gulp-print');

gulp.task('default', ['jade', 'sass', 'js', 'connect', 'watch']);

gulp.task('jade', function() {
  gulp.src('./src/jade/*.jade')
    .pipe(jade())
    .pipe(ga({url: 'auto', uid: config.gaId, tag: 'body',sendPageView: true, minify: false, anonymizeIp: false}))
    .pipe(gulp.dest('./public/'));
});

gulp.task('sass', function () {
  gulp.src('./src/sass/style.scss')
    .pipe(sass({
      includePaths: [
        config.bowerDir + '/bootstrap/scss',
        config.bowerDir + '/font-awesome/scss'
      ],
      outputStyle: 'compressed'
    })
    .on('error', sass.logError))
    .pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
    .pipe(gulp.dest('./public/css'));
});

gulp.task('connect', function() {
  connect.server({
    root: 'public',
    livereload: true
  });
});

gulp.task('watch', function () {
  gulp.watch(['./src/jade/**/*.jade'], ['jade']);
  gulp.watch(['./src/sass/**/*.scss'], ['sass']);
  gulp.watch(['./src/js/**/*.js'], ['js']);
  watch(['./public/**/*.html', './public/**/*.css', './public/**/*.js']).pipe(connect.reload());
});

gulp.task('js', function () {
  return gulp.src([
    './node_modules/fontfaceobserver/fontfaceobserver.js',
    './bower_components/jquery/dist/jquery.min.js',
    './bower_components/bootstrap/js/dist/util.js',
    './bower_components/bootstrap/js/dist/collapse.js',
    './bower_components/picturefill/dist/picturefill.js',
    './src/js/modernizr.js',
    './src/js/js.js'
    ])
    .pipe(concat({ path: 'js.js'}))
    .pipe(uglify())
    .pipe(gulp.dest('./public/js'));
});

Full source is here https://gist.github.com/dandaka/3e342158763f9ccbd23305eecfd0b69c

Thank you!

Upvotes: 2

Views: 1409

Answers (3)

G07cha
G07cha

Reputation: 4164

Also besides of @TheFallen's suggestion, you good practice will be to create a separate task and place it at the end of watch tasks.

var gulp = require('gulp');
var runSequence = require('run-sequence');

gulp.task('reload', function() {
   connect.reload();
});

gulp.task('watch', function () {
  gulp.watch(['./src/jade/**/*.jade'], function() {
    runSequence('jade', 'reload');
  })

  gulp.watch(['./src/sass/**/*.scss'], function() {
    runSequence('sass', 'reload');
  });

  gulp.watch(['./src/js/**/*.js'], function() {
    runSequence('js', 'reload');
  });
});

UPD: As @Fencer correctly pointed out, tasks are executed simultaneously which could sometimes lead to the case when page is reloaded before the previous task is completed, I've added run-sequence package usage to avoid this issue.

Upvotes: 2

Fencer
Fencer

Reputation: 1088

I ran into the same problem recently and both solutions mentioned here did not work as I pointed out in my comments.

Using Gulp 3 the only working solution I could come up with is the following (I did not use gulp-connect though but the actual solution should be generic):

gulp.task('jade', function() {
    var stream = gulp.src('./src/jade/*.jade')
        .pipe(jade())
        .pipe(ga({url: 'auto', uid: config.gaId, tag: 'body',sendPageView: true, minify: false, anonymizeIp: false}))
        .pipe(gulp.dest('./public/'))
        .on('end', function() {
            livereload.reload();
        });
});

...

gulp.task('watch', function () {
    livereload.listen();
    gulp.watch(['./src/jade/**/*.jade'], ['jade']);
    ...
});

I do not know how Gulp works internally, but on('end'...)seems to actually wait until all operations of the stream have finished.

Using Gulp 4 there may be a solution that looks a lot like the one of @Konstantin Azizov.

gulp.task('reload', function() {
    connect.reload();
});

gulp.task('watch', function () {
    gulp.watch(['./src/jade/**/*.jade'], gulp.series('jade', 'reload'));
    ...
});

Or maybe even just:

gulp.task('watch', function () {
    gulp.watch(['./src/jade/**/*.jade'], gulp.series('jade', function() {
        connect.reload();
    }));
    ...
});

Please be aware that I did not test the Gulp 4 solutions. I'm a bit reluctant to switch to version 4 because it has still not officially been released. However it is very tempting.

Upvotes: 2

thefallen
thefallen

Reputation: 9749

Place .pipe(connect.reload()) at the end on each of the tasks, like the js for example:

return gulp.src([
    ...
    ])
    .pipe(concat({ path: 'js.js'}))
    .pipe(uglify())
    .pipe(gulp.dest('./public/js'))
    .pipe(connect.reload());

Because right now when it's on the watch watch([...]).pipe(connect.reload()); it will fire when the compilation has started bu not necessarily finished.

Upvotes: 1

Related Questions