Gulp.js, watch task runs twice when saving files

2019-01-17 23:55发布

Given the following piece of code from my gulpfile.js, everytime I save or change a file, the task runs twice instead of one single time, why is that? I just want it to run one time.

var gulp = require('gulp');

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

  gulp.watch('server/**/*.js', function(){
    console.log('This runs twice everytime I change/save a javascript file located at server/**/*.js');
  }); 

});

I have also experienced the same with grunt and the plugin called grunt-contrib-watch.

12条回答
做个烂人
2楼-- · 2019-01-18 00:29

Had the same issue and it turns out, that gulp-sourcemaps causes it (see -> Using source maps causes task to run twice)

Get a solution with gulp-notify and the attribute onLast:

.pipe(notify({message: 'YOUR MESSAGE', onLast: true}));
查看更多
欢心
3楼-- · 2019-01-18 00:32

This worked for me

.pipe(watch('/**/*.less', { awaitWriteFinish: true }))

https://github.com/paulmillr/chokidar#api

查看更多
Explosion°爆炸
4楼-- · 2019-01-18 00:33

The problem is occurring because your editor, in this case Coda 2, is modifying the file twice on save. The same problem occurs in vim because of how vim creates buffer backups on save.

The solution to the problem in vim is to add

set nowritebackup

to your ~/.vimrc file. This changes the default save protocol to only make one edit to the original file.

In other words, the default save protocol is as follows:

  1. Write the buffer to the backup file
  2. Delete the original file
  3. Rename the backup to the name of the original file

And adding set nowritebackup simply replaces the original file on save. This protocol exists to reduce risk of data loss in the event of an I/O error on save.

查看更多
Ridiculous、
5楼-- · 2019-01-18 00:36

You should be able to use gulp-batch to batch the changes, since it has a debounce option.

Something like this:

gulp.src(['server/**/*.js'], batch({debounce: 50}, function(events) {
    return events
        .pipe(...); // your code here
}));
查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-01-18 00:37

Hint: the debounce parameter only works for the SAME file/event. If multiple events/files change, it won't help. Sometimes (e.g. I copied files into the a directory being served by my local server) gulp-cached might help, sometimes excluding certain files/patterns (e.g. the sourcemaps files) might help (use ! to negate the selection). e.g.

gulp.watch(['js/**/*', '!js/**/*.map'])
查看更多
唯我独甜
7楼-- · 2019-01-18 00:37

One year later ...

Using

  • nodejs 0.10.25
  • gulp 3.8.10

Gaz debounceDelay option did not change anything for me, neither did I understand how to use gulp-batch callback argument :/ ...

To avoid consecutives task calls after several files have been changed, I used the oldschool setTimeout function:

// ...
var
SRC = ['js/*.js', '!js/*.min.js'], DEST = 'js',
processJs = function(){
    util.log('Processing: ['+ SRC.join(' | ') +']');
    var stream = gulp.src(SRC)
        .pipe(uglify())
        .pipe(concat('scripts.min.js'))
        .pipe(gulp.dest(DEST));
    return stream;
};


gulp.task('default', function(){
    var delay = 2000, timer,
        watcher = gulp.watch(
            SRC,
            // Callback triggered whatever the event type is (added / changed / deleted)
            function(event) { // .path | .type
                // If the timer was assigned a timeout id few time ago..
                // Prevent last postpone task to be run
                if(timer){
                    clearTimeout(timer);
                }
                // Postpone the task
                timer = setTimeout(
                    function(){processJs();timer=0;}
                    ,delay
                );
            }
        );
    util.log("/!\\ Watching job "+ Array(25).join('~'));
});
查看更多
登录 后发表回答