Issue with gulp watch on files modified through ftp: how to delay task?

Hi!
With Gulp I encountered an issue when watching files I modify through FTP.
When I develop, I launch gulp watch and then I modify files (PHP, LESS, ecc.) using FTP. Apparently the watch task trigger “too fast” when the file is uploaded, and I think it runs on an almost empty file, since sometimes all the contents of the file are not in the final css or js (this happen very often with large files).

How can I delay the watch tasks for a couple of seconds, so I can be sure that the file has been completely uploaded?

Whoa there. Take the FTP out of the picture and setup a local development environment.

1 Like

In case someone finds this post, it is possible to avoid this issue with FTP by modifying the gulp watch function. Add this to your gulpfile.js, probably best right after all the defines:

// Add debounce to gulp watch for FTP
(function ftp_debounce_fix(){
  
  var watch = gulp.watch;
  
  // Overwrite the local gulp.watch function
  gulp.watch = function(glob, opt, fn){
    var _this = this, _fn, timeout;
    
    // This is taken from the gulpjs file, but needed to
    // qualify the "fn" variable
    if ( typeof opt === 'function' || Array.isArray(opt) ) {
      fn = opt;
      opt = null;
    }
    
    // Make a copy of the callback function for reference
    _fn = fn;
    
    // Create a new delayed callback function
    fn = function(){
      
      if( timeout ){
        clearTimeout( timeout );
      }
      
      timeout = setTimeout( Array.isArray(_fn) ? function(){
        _this.start.call(_this, _fn);
      } : _fn, 150 );
      
    };
    
    return watch.call( this, glob, opt, fn );
  };
  
})();

If you still have issues, you can try increasing the “150” timeout. Its not a bulletproof solution, and obviously, a local dev environment is preferable, but if you are working through FTP, this should help.

2 Likes

@ben - I really, really, really appreciate what you’re doing with Sage, I love the project and I think what you’re doing is amazing. I also appreciate that you’re an evangelist, and think that this has resulted in Sage being the best starter theme for WordPress.

That being said,

in my case is not a practical answer to this issue… Like OP I work in an office where “FTP to the server” is the required protocol. I was very frustrated with the gulp watch failing 89% of the time, having to result to manually running gulp styles on the server every time I changed a single line. I’m glad @fabrizim posted a fix!

Hopefully I’ll eventually convince everyone to migrate over to Bedrock and using local development environments, but for the time being I’m glad to have found a workable solution! Thanks!

I’ve similar issue - by uploading file via ftp-client (Transmit) it create FileName_safe_save_ID.ext files

And my solution is using other wath library - chokidar

gulp.task('watch', function () {
    var watcher = chokidar.watch('./stylesheets/**/*.scss');

    watcher.on('ready', function () {

        watcher.on('all', function (e, path) {

            if (e == 'change' && !re_safe_save.test(path))
                gulp.start('sass');

            if (e == 'unlink' && re_safe_save.test(path))
                gulp.start('sass');
        });
    })
});
1 Like

Great tip! chokidar also has awaitWriteFinish option, which is specially designed to handle such cases!
to watch functions.php and *.tpl files and run templates task on change, simple code would be:

var chokidar = require('chokidar');
gulp.task('watch', function () {
chokidar.watch(['functions.php', 'template/**/*.tpl'], { // watch files/globs in array
    awaitWriteFinish: true, //this is required option for delayed watch
        persistent: true,
    }).on('ready', function () { //when scan completed
        this.on('all', function (e, path) {
            if (e == 'change') { //on change. Works on FTP uploads!
                gulp.start('templates'); //Start task 'templates'
            }
        });
    });
});