0

So I'm trying to compile pug (jade), javascript and sass files with Gulp V4, and using browserSync to reload the browser when any of these files change. There are a lot of guides out there, but no matter which way I write the code, it just doesn't seem to get the task order right. Im using gulp.series to set the task order, but browserSync doesn't want to play ball.

Here's a print of my Gulp file:

var gulp = require('gulp'),
... etc.

var paths = {
    sass: ['src/scss/**/*.scss'],
    js:   ['src/js/**/*.js'],
    pug:  ['src/**/*.pug']
};

// Shared Tasks:
//*------------------------------------*/

gulp.task('clean', function(done){
    del(['dist/assets/**/*.css', 'dist/assets/**/*.map', 'dist/assets/**/*.js']);
    done();
});

// App Specific Tasks:
//*------------------------------------*/

// Sass
gulp.task('build-sass', function(){
    gulp.src(paths.sass)
        return sass(paths.sass, {
            style: 'expanded'
        })
        .on('error', sass.logError)
        .pipe(prefix('last 2 version', '> 1%', 'ie 8', 'ie 9'))
        .pipe(sourcemaps.write())
        .pipe(gulp.dest('dist/assets/css'))
        .pipe(cleanCSS({ advanced: false, keepSpecialComments: 0 }))
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('dist/assets/css'));
});

// JS
gulp.task('build-js', function(done){
    gulp.src(paths.js)
        .pipe(concat('all.js'))
        .pipe(gulp.dest('dist/assets/js'))
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify())
        .pipe(gulp.dest('dist/assets/js'))
        done();

// Pug
gulp.task('build-pug', function buildHTML(done){
    gulp.src(['src/**/*.pug'], {
        base: 'src'
    })
    .pipe(pug())
    .pipe(gulp.dest('./dist/'))
    done();
});


// Service Tasks:
//*------------------------------------*/

// Delete the compiled views dir.
gulp.task('remove', function(done){
    del(['dist/views/**/']);
    done();
});

// Serve the site locally and watch for file changes
gulp.task('serve', function(done){
    browserSync.init({
        server: {
            baseDir: './dist/',
            notify: false,
            open: false
        }
    });

   // Watch & Reload Pug Files
   gulp.watch([paths.pug], gulp.series('build-pug')).on('change', browserSync.reload);
   // Watch & Reload Sass Files
   gulp.watch([paths.sass], gulp.series('build-sass')).on('change', browserSync.reload);
});


gulp.task('default', gulp.series('clean', 'build-sass', 'build-js', 'build-pug', 'remove', 'serve', function(done){
    done();
}));

And the terminal console log outputs this when starting gulp:

$ gulp
[13:09:33] Using gulpfile ~/Dropbox Aaron/Dropbox (Personal)/01_Me/01_Dev/01_My Work/*Template/gulpfile.js
[13:09:33] Starting 'default'...
[13:09:33] Starting 'clean'...
[13:09:33] Finished 'clean' after 2.64 ms
[13:09:33] Starting 'build-sass'...
[13:09:33] Finished 'build-sass' after 443 ms
[13:09:33] Starting 'build-js'...
[13:09:33] Finished 'build-js' after 4.42 ms
[13:09:33] Starting 'build-pug'...
[13:09:33] Finished 'build-pug' after 3.15 ms
[13:09:33] Starting 'remove'...
[13:09:33] Finished 'remove' after 656 μs
[13:09:33] Starting 'serve'...
[BS] Access URLs:
-------------------------------------
      Local: http://localhost:3000
   External: http://10.130.91.51:3000
-------------------------------------
         UI: http://localhost:3001
UI External: http://10.130.91.51:3001
-------------------------------------
[BS] Serving files from: ./dist/

And this when I change a file within the watched files:

[BS] File changed: src/scss/4_elements/_elements.page.scss
[13:12:33] Starting 'build-sass'...
[13:12:34] write ./style.css
[13:12:34] Finished 'build-sass' after 366 ms

So what seems to me to be happening in this instance, the file is changing, browserSync reloads the page, and then 'build-sass' starts. Which is the wrong way round. I obviously want to build the sass, then reload the page. I have to save 2 times for the browser to refresh the code I want.

Some of the code I've used is directly from the browserSync documentation:

https://www.browsersync.io/docs/gulp#gulp-reload

This doesn't seem to work.

Aaron
  • 83
  • 1
  • 1
  • 5
  • Does the browser reload when you modify a .pug file? You do not have a done() call at the end of 'build-sass' but you do have a return statement - although it looks a little unfamiliar to me in that form - so that may be enough. I have another suggestion if pug changes don't trigger a reload. – Mark Oct 05 '16 at 22:44
  • The done is a required event from Gulp V4. Adding that doesn't improve the result. So if I want to reload the browser when I update my views, or jade/pug files how do I do that without triggering a reload when a .pug changes? – Aaron Oct 06 '16 at 08:02

1 Answers1

1

Your log output looks right. First it runs 'default' and then your series of tasks. Later when you modify a sass file, it starts 'build-sass'. The only problem is it doesn't reload via browserSync.reload(). So I believe the problem may be here:

gulp.watch([paths.sass], gulp.series('build-sass')).on('change', browserSync.reload);

I highly recommend

https://github.com/gulpjs/gulp/blob/4.0/docs/recipes/minimal-browsersync-setup-with-gulp4.md

that is the gulp4.0 recipe to do exactly what you are trying to do. I am using pretty much what they have there, so if you have problems getting their code to work I can help. Here is my working code:

function serve (done) {
  browserSync.init({
  server: {
    baseDir: "./",
    index: "home.html"
  },
  ghostMode: false
 });
 done();
}

function reload(done) {
  browserSync.reload();
  done();
}

var paths = {
  styles: {
    src: "./scss/*.scss",
    dest: "./css"
  },
  scripts: {
    src: "./js/*.js",
    dest: "./js"
  }
};

function watch() {
  gulp.watch(paths.scripts.src, gulp.series(processJS, reload));
  gulp.watch(paths.styles.src,  gulp.series(sass2css,  reload));
  gulp.watch("./*.html").on("change", browserSync.reload);
}

var build = gulp.series(serve, watch);

gulp.task("sync", build);

function sass2css() {
  return gulp.src("./scss/*.scss")
    .pipe(cached("removing scss cached"))
    // .pipe(sourcemaps.init())
    .pipe(sass().on("error", sass.logError))
    // .pipe(sourcemaps.write("./css/sourceMaps"))
    .pipe(gulp.dest("./css"));
}

function processJS() {
  return gulp.src("./js/*.js")
    .pipe(sourcemaps.init())
    // .pipe(concat("concat.js"))
    // .pipe(gulp.dest("./concats/"))
    // .pipe(rename({ suffix: ".min" }))
    // .pipe(uglify())
    .pipe(sourcemaps.write("./js/sourceMaps/"))
    .pipe(gulp.dest("./js/maps/"));
}

Note the general use of functions instead of 'tasks' and particularly the reload(done) function. You might try simply adding that to your watch statements like

gulp.watch([paths.sass], gulp.series('build-sass', reload);

after you have added the reload function, that might be enough to fix your problem without making all the other changes as in my code. Or you might simply have to add a return statement to your 'build-sass' task so gulp knows that task has completed. Good luck.

Mark
  • 143,421
  • 24
  • 428
  • 436
  • Thanks Mark, I havent tried this yet but will give it a go! Thanks for your help. Will let you know if this works! – Aaron Oct 10 '16 at 09:29
  • Thanks Mark, this worked a treat! Must have been a combination of both using done(); and using the functions instead of gulp tasks. – Aaron Oct 13 '16 at 09:59
  • Glad it helped - it runs much faster that my gulp 3 version did too. – Mark Oct 13 '16 at 17:38