Alpha
Alpha

Reputation: 7868

How to setup gulp-watch with gulp-connect livereload?

Most questions and answers on this site do not contain an easy-to follow general approach to using these two libraries together.

So, being that we use the gulp-connect npm package, and we want to make use of the gulp-watch npm package, how do we set it up so that we can:

Upvotes: 1

Views: 3950

Answers (2)

neotam
neotam

Reputation: 2731

Bringing up to speed, as per current stable gulp release

gulp.task API isn't the recommended pattern anymore. Use exports object to make public tasks

From official documentation: https://gulpjs.com/docs/en/api/task#task

To Configure watch and livereload you need following

  • gulp.watch
  • gulp-connect

watch function is available in gulp module itself

install gulp-connect using npm install --save-dev gulp-connect

To configure gulp-connect server for livereload we need to set property livereload to true

Run all tasks followed by task that calls watch function in which globs and task are given. Any changes to files that match globs trigger task passed to watch().

task passed to watch() should signal async complection else task will not be run a second time. Simple works: should call callback or return stream or promise

Once watch() is configured, append .pipe(connect.reload()) followed by pipe(dest(..)) where ever you think created files by dest are required to reload

Here is simple working gulpfile.js with connect lifereload

const {src, dest, watch, series, parallel } = require("gulp"); 
const htmlmin = require("gulp-htmlmin");
const gulpif = require("gulp-if");
const rename = require('gulp-rename');
const connect = require("gulp-connect");

//environment variable NODE_ENV --> set NODE_ENV=production for prouduction to minify html and perform anything related to prod
mode = process.env.NODE_ENV || 'dev';  
var outDir = (mode != 'dev') ? 'dist/prod': 'dist/';
const htmlSources = ['src/*.html'];

function html() {
  return src(htmlSources)
  .pipe(gulpif(
      mode.toLowerCase() != 'dev', 
      htmlmin({
        removeComments: true, 
        collapseWhitespace: true,
        minifyCSS: true,
        minifyJS: true
      })
    )
  )
  .pipe(dest(outDir))
  .pipe(connect.reload()); 
}

function js(){
  return src('src/*.js')
  .pipe(uglify())
  .pipe(rename({ extname: '.min.js' }))
  .pipe(dest(outDir))
  .pipe(connect.reload());
}

function server() {
  return connect.server({
    port: 8000,
    root: outDir,
    livereload: true
  })
}

function watchReload() {
  let tasks = series(html, js);
  watch(["src/**"], tasks);
}

exports.html = html; 
exports.js = js;
exports.dev = parallel(html, js, server, watchReload);

Configure connect server with livereload property

function server() {
      return connect.server({
        port: 8000,
        root: outDir,
        livereload: true  //essential for live reload 
      })
    }

Notice .pipe(connect.reload()) in the above code. It is essential that stream of required files to be piped to connect.reload() else it may not work if you call connect.reload() arbitrarily

function html() {
  return src(htmlSources)
  .pipe(gulpif(
      mode.toLowerCase() != 'dev', 
      htmlmin({
        removeComments: true, 
        collapseWhitespace: true,
        minifyCSS: true,
        minifyJS: true
      })
    )
  )
  .pipe(dest(outDir))
  .pipe(connect.reload());  //Keep it if you want livereload else discard 
}

Since we configure public task dev following command will execute all tasks followed by connect and watchReload

gulp dev

Upvotes: 2

Alpha
Alpha

Reputation: 7868

First, you will define your build task. This can have pre-required tasks, can be a task of some sort, it doesn't matter.

gulp.task('build', ['your', 'tasks', 'here']);

Then, you will need to activate the connect server. It is important that you are serving the result of the compilation (in this example, the dist directory) and you're enabling livereload with the livereload: true parameter.

const connect = require('gulp-connect');

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

Finally, you will setup your watch logic. Note that we're using watch and not gulp.watch. If you decide to change it, notice that their APIs are different and they have different capabilities. This example uses gulp-watch.

const watch = require('gulp-watch');

gulp.task('watch-and-reload', ['build'], function() {
  watch(['src/**'], function() {
    gulp.start('build');
  }).pipe(connect.reload());
});

gulp.task('watch', ['build', 'watch-and-reload', 'server']);

The watch-and-reload task will depend on the build task, so that it ensures to run at least one build.

Then, it will watch for your source files, and in the callback, it will start the build task. This callback gets executed every time that a file is changed in the directory. You could pass an options object to the watch method to be more specific. Check the usage API in their repository.

Also, you will need to start the build action, for which we're using gulp.start. This is not the recommended approach, and will be deprecated eventually, but so far it works. Most questions with these issues in StackOverflow will look for an alternative workaround that changes the approach. (See related questions.)

Notice that gulp.start is called synchronously. This is what you want, since you want to allow the build task to finish before you proceed with the event stream.

And finally, you can use the event stream to reload the page. The event stream will correctly capture what files changed and will reload those.

Upvotes: 6

Related Questions