Search code examples
node.jsgulpwebpacklivereloadnodemon

Gulp reloads same file many times


I am using gulp to run both client and server in my project. In the terminal, seems like the same files are reloaded many times. What could be the reason and how to fix this?

[12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/_runMainLayout.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/_runMainLayout.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/_runMainLayout.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/_runMainLayout.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/_runMainLayout.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/_runMainLayout.js reloaded.

[12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/getData.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/getData.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/getData.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/getData.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/getData.js reloaded. [12:00:03] /Users/verinasutd/Dev/Projects/metaBranch1/app/js/getData.js reloaded.

At the same time also nodemon, notify, live-reload. It does feel excessive however this was the way somehow that could work the last time the project was developed. Below is the gulpfile.

// gulpfile.js
var gulp = require('gulp');
var nodemon = require('gulp-nodemon');

var notify = require('gulp-notify');
var livereload = require('gulp-livereload');
var webpack = require('webpack-stream’);

gulp.task('js', function () {
   gulp.src('./app/js/*.js')
    .pipe(livereload());
});

gulp.task('watch', function () {
   livereload.listen();
   gulp.watch(['./app/js/*.*'], ['js']); //update
});

gulp.task('server', function(){
   // listen for changes
   livereload.listen();
   // configure nodemon
   nodemon({
     // the script to run the app
     script: 'run.js',
     ext: 'js'
   }).on('restart', function(){
   // when the app has restarted, run livereload.
     gulp.src('run.js')
       .pipe(livereload());
   })
 });


 gulp.task('client', function(){

 gulp.src('./app/js/es6/main.js') //'src/entry.js'
   .pipe(webpack( require('./webpack.config.js') ))
   .pipe(gulp.dest(__dirname + '/app/js'))
   .pipe(livereload());

 });

 gulp.task('default', function() {
 });

 gulp.task('default', ['server','client','watch']);

Solution

  • The server task:

    There is no real reason to start a livereload server, which is mean to notify the client if any front-end components have updated, from a task that is supposed to only start the back-end server.

    Also, from gulp-livereload's npm page:

    livereload.listen([options])
    Starts a livereload server. It takes an optional options parameter that is the same as the one noted above. Also you dont need to worry with multiple instances as this function will end immidiately if the server is already runing.

    So basically either this server, or the one you start in the watch task, are killed on start, so why even bother starting both?

    Also on the nodemon section of this task you're loading your server's entry point and piping it to the livereload server.

    livereload([options])
    Creates a stream which notifies the livereload server on what changed.

    What you're doing is telling the livereload server to notify the client that the server script has updated, while this script is not even present in the client bundle (why would it?).

    If your intent whas to reload the page when the server script updates, you should have used instead the livereload.reload() method:

    livereload.reload([file])
    You can also tell the browser to refresh the entire page. This assumes the page is called index.html, you can change it by providing an optional file path or change it globally with the options reloadPage.

    The client task:

    Nice thing about webpack-stream is that if you set watch: true in it's config, he will automatically watch for changes and pipe the recompiled bundle every time.
    In short you don't need all the gulp.watch(...) stuff.

    Reordering the tasks:

    We are at the point where the js task is completely pointless, and the watch task only runs the livereload server.
    Also the client task only compiles the javascript, which doesn't make much sense.

    IMHO it would be wise to rename the client task to js, then create a js:watch task that also watches for changes.
    Then working a bit on task dependencies we could say that we want a client task that runs all the tasks that prepare our client files (html, styles, scripts,... ), and we can define it as follows:

    gulp.task('client', ['js']);
    

    Then we know that the watch task depends on the client files, as it's role is to monitor them for changes. So we write:

    gulp.task('watch', ['client', 'js:watch'], function () {
        livereload.listen();
    }
    

    Then, thanks to the new established dependency system, we can define the default task as follows:

    gulp.task('default', ['server', 'watch']);
    

    Conclusion

    You can see a full revision of your build script on pastie.

    This is not meant to be a final/optimal/perfect solution, it just makes everything a bit more clear on how it works and how it interacts with other tasks/components.

    I'd like to add that gulp's build script is a simple js file interpreted by node, so you could use the es6 features natively implemented by the v8 engine (const/let, arrow functions and much more).