gulp.watch() not working with ftp update

I have recently learnt gulp and scripted this gulp script on my local computer, so that it can watch for any changes, and compile my javascripts (in this case, ./js/main.js with its dependencies) into a single file ./js/bundle.js :

var gulp = require('gulp');
// Plugins
var jshint = require('gulp-jshint');
var browserify = require('gulp-browserify');
var rename = require('gulp-rename');

// Lint Task
gulp.task('lint', function() {
  return gulp.src(['./js/**/*.js', '!./js/bundle.js'])
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
});

// browserify task
gulp.task('b', function() {
  gulp.src('js/main.js')
    .pipe(browserify())
    .pipe(rename('bundle.js'))
    .pipe(gulp.dest('js/'));

});

// Watch Files For Changes
gulp.task('watch', function() {
  gulp.watch(['./js/*.js', './js/**/*.js', '!./js/bundle.js'], ['lint', 'b'])
    .on('change', function(event) {
      console.log("n============");
      console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
    });
});

// Default Task
gulp.task('default', ['lint', 'watch']);

It runs well on my local computer (Windows 7), so I tried putting it to my remote Ubuntu server, and let it watch for any ftp updates and browserify them.

In other words, I want to code remotely and update ./js/main.js through ftp, and have gulp watch for the changes and browserify it automatically.

The problem is: Gulp recognizes the change and logged on the console:

File /home/wordpress/public_html/cm/mobileCoder02/src/js/main.js was changed, running tasks...
[09:27:47] Starting 'lint'...
[09:27:47] Starting 'b'...
[09:27:47] Finished 'b' after 34 μs
[09:27:47] Finished 'lint' after 6.71 ms

But the output file, bundle.js contains nothing but the module loader script:

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

},{}]},{},[1])

If I change the task to

// browserify task
gulp.task('b', function() {
  setTimeout(function() {
    gulp.src('js/main.js')
      .pipe(browserify())
      .pipe(rename('bundle.js'))
      .pipe(gulp.dest('js/'));
  }, 1000);

});

Then the code runs OK.

I would like to ask why it have to wait for some time before browserifying. Shouldn't gulp.watch() be firing 'change' event after the ftp transfer is finished? If not, shouldn't it be at least using the old version?

Thank you.


At a first glance, I think that behavior is mainly due to how the FTP Protocol works.

The fact is that, in each mode of transfer, Stream , Block or Compressed , not all the data is send at one time. All your transfers are cut into small pieces of data, actually 8 bits of byte size . That's how FTP clients can determine the progress of a transfer, by comparing how many packets were successfully transferred with the actual number of packets the file you want to transfer consists.

All this to say that when you start the upload of you main.js file, the client begin to transfer the data (by default using the Stream mode, which is as its name suggest, a stream of bytes (Hey ! Just as gulp !)), sending in most of the cases the STOR command, creating a file on the server if it doesn't exists or replace all its content otherwise.

Since the gulp watcher is triggered on each file change, a single tick of a successful transfer packet can launch your task, even if the file is not done uploading. And like I say, when the file already exists on the server, all its content is cleaned before the data is transferred, so your task will run with an empty or partial file.

Your timeout helps here to wait until the file is done uploading , by the way 1 second works for now but seems a little short to me, specially if you have a poor connection or that your file size gonna expand.

You can have a look to the RFC 959 for more details, which is the current standard specification for the FTP Protocol .


I had the same issue. Instead of using gulp-watch I am now using the Python library when-changed. It monitors a directory for file changes, but it does not seem to have the same issue with FTP uploads as gulp does.

I've removed the watch part of my gulpfile and am now running the 'watch'-part with the following command:

when-changed -r /var/www/website/css/internal /var/www/website/js/internal -c gulp
链接地址: http://www.djcxy.com/p/32902.html

上一篇: 使用Gulp和Browserify捆绑多个文件

下一篇: gulp.watch()不能用于ftp更新