gulp.watch() не работает с обновлением ftp

Недавно я изучил gulp и написал этот скрипт gulp на своем локальном компьютере, чтобы он мог отслеживать любые изменения и компилировать мои javascripts (в данном случае ./js/main.js с его зависимостями) в один файл ./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']);

Он хорошо работает на моем локальном компьютере (Windows 7), поэтому я попытался поместить его на свой удаленный сервер Ubuntu и позволить ему следить за любыми обновлениями ftp и просматривать их.

Другими словами, я хочу кодировать удаленно и обновлять ./js/main.js через ftp, а gulp отслеживать изменения и автоматически просматривать их.

Проблема в том, что Gulp распознает изменение и входит в консоль:

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

Но выходной файл bundle.js не содержит ничего, кроме скрипта загрузки модуля:

(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])

Если я изменю задачу на

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

});

Тогда код работает нормально.

Я хотел бы спросить, почему он должен ждать некоторое время, прежде чем браузер. Разве gulp.watch() не должно запускать событие «change» после завершения передачи по ftp? Если нет, то не следует ли хотя бы использовать старую версию?

Спасибо.


person vickson    schedule 27.07.2014    source источник


Ответы (2)


На первый взгляд, я думаю, что такое поведение в основном связано с тем, как работает FTP Protocol.

Дело в том, что в каждом режиме передачи, Stream, Block или Compressed, не все данные отправляются одновременно. Все ваши переводы нарезаются на небольшие фрагменты данных, фактически 8 bits из byte size. Вот как FTP clients может определить ход передачи, сравнивая, сколько packets было успешно передано, с фактическим количеством packets файлов, которые вы хотите передать.

Все это для того, чтобы сказать, что когда вы запускаете upload вашего файла main.js, client начинают передавать данные (по умолчанию используется режим Stream, который, как следует из названия, является stream из bytes (Эй! Так же, как gulp!)) , отправляя в большинстве случаев команду STOR, создавая файл на сервере, если он не существует, или заменяя все его содержимое в противном случае.

Поскольку gulp watcher срабатывает при каждом изменении файла, один тик успешного пакета передачи может запустить вашу задачу, даже если загрузка файла еще не завершена. И, как я уже сказал, когда файл уже существует на сервере, все его содержимое очищается перед передачей данных, поэтому ваш task будет работать с пустым или неполным файлом.

Ваш timeout помогает здесь дождаться завершения загрузки файла, кстати, 1 second пока работает, но мне кажется немного коротким, особенно если у вас плохое соединение или размер вашего файла будет увеличиваться.

Дополнительную информацию можно найти в RFC 959, который является текущей стандартной спецификацией для FTP Protocol.

person Balthazar    schedule 27.07.2014

Я была такая же проблема. Вместо использования gulp-watch я теперь использую библиотеку Python when-changed. Он отслеживает каталог на наличие изменений файлов, но, похоже, у него нет такой же проблемы с загрузкой FTP, как у gulp.

Я удалил часть наблюдения из моего gulpfile и теперь запускаю часть наблюдения с помощью следующей команды:

when-changed -r /var/www/website/css/internal /var/www/website/js/internal -c gulp
person PetaPetaPeta    schedule 17.05.2015