Я разрабатываю Gulpfile
. Можно ли его перезапустить, как только он изменится? Я разрабатываю его в CoffeeScript. Может ли Gulp
смотреть Gulpfile.coffee
, чтобы перезапустить после сохранения изменений?
Как можно перезапустить Gulp при каждом изменении Gulpfile?
Ответы (14)
Вы можете создать task
, который будет gulp.watch
вместо gulpfile.js
, и просто spawn
еще один gulp child_process.
var gulp = require('gulp'),
argv = require('yargs').argv, // for args parsing
spawn = require('child_process').spawn;
gulp.task('log', function() {
console.log('CSSs has been changed');
});
gulp.task('watching-task', function() {
gulp.watch('*.css', ['log']);
});
gulp.task('auto-reload', function() {
var p;
gulp.watch('gulpfile.js', spawnChildren);
spawnChildren();
function spawnChildren(e) {
// kill previous spawned process
if(p) { p.kill(); }
// `spawn` a child `gulp` process linked to the parent `stdio`
p = spawn('gulp', [argv.task], {stdio: 'inherit'});
}
});
Я использовал yargs
, чтобы разрешить выполнение "основной задачи" после перезагрузки. Итак, чтобы запустить это, вы должны позвонить:
gulp auto-reload --task watching-task
И для проверки вызовите touch gulpfile.js
или touch a.css
, чтобы просмотреть журналы.
auto-reload
и запустить ее как gulp auto-reload --task foo
, иначе вы можете получить форк-бомбу, рекурсивно запускающую задачу по умолчанию.
- person OverZealous; 06.04.2014
2014-07-29 11:48 gulp[74366] (CarbonCore.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
) и, например. localhost:3000
номер порта увеличивается при использовании BrowserSync
- person Murray Rowan; 29.07.2014
cross_spawn
. npmjs.com/package/cross-spawn
- person DerekMT12; 21.01.2016
spawnChildren()
) передается аргумент обратного вызова, который должен быть вызван после выполнения spawnChildren()
, иначе задача auto-reload
никогда не вернется к отслеживанию дальнейших изменений (т. е. перезагрузка работает только один раз). github.com/gulpjs/gulp/blob/ v4.0.0/docs/API.md#fn-1
- person Sphinxxx; 24.03.2018
Я создал gulper, который является оболочкой gulp.js cli для перезапуска gulp при изменении gulpfile.
Вы можете просто заменить gulp на gulper.
$ gulper <task-name>
Для этой цели я использую небольшой сценарий оболочки. Это работает и в Windows.
Нажмите Ctrl+C
, чтобы остановить скрипт.
// gulpfile.js
gulp.task('watch', function() {
gulp.watch('gulpfile.js', process.exit);
});
Сценарий оболочки Bash:
# watch.sh
while true; do
gulp watch;
done;
Версия Windows: watch.bat
@echo off
:label
cmd /c gulp watch
goto label
Я получил кучу ошибок EADDRINUSE
с решением в ответе Кайо Кунья. Мой gulpfile открывает локальный веб-сервер с connect и LiveReload. Похоже, что новый процесс gulp ненадолго сосуществует со старым, прежде чем старый процесс будет уничтожен, поэтому порты все еще используются процессом, который скоро умрет.
Вот похожее решение, которое решает проблему сосуществования (в основном основанное на этом ):
var gulp = require('gulp');
var spawn = require('child_process').spawn;
gulp.task('gulp-reload', function() {
spawn('gulp', ['watch'], {stdio: 'inherit'});
process.exit();
});
gulp.task('watch', function() {
gulp.watch('gulpfile.js', ['gulp-reload']);
});
Это работает довольно хорошо, но имеет один довольно серьезный побочный эффект: Последний процесс gulp отключается от терминала. Таким образом, когда gulp watch
завершает работу, потерянный процесс gulp все еще выполняется. Мне не удалось обойти эту проблему, дополнительный процесс gulp можно остановить вручную или просто сохранить синтаксическую ошибку в gulpfile.js.
process.argv.shift(); spawn(process.argv.shift(), process.argv, {stdio: 'inherit'}); process.exit()
- person Mbrevda; 15.01.2016
Другое решение для этого — обновить файл require.cache
.
var gulp = require('gulp');
var __filenameTasks = ['lint', 'css', 'jade'];
var watcher = gulp.watch(__filename).once('change', function(){
watcher.end(); // we haven't re-required the file yet
// so is the old watcher
delete require.cache[__filename];
require(__filename);
process.nextTick(function(){
gulp.start(__filenameTasks);
});
});
once
, иначе у вас могут быть утечки памяти
- person stringparser; 11.11.2014
end
его
- person stringparser; 01.05.2015
Я знаю, что это очень старый вопрос, но это главный комментарий в Google, поэтому он все еще очень актуален.
Вот более простой способ, если ваш исходный gulpfile.js находится в другом каталоге, чем тот, который используется. (Это важно!) Он использует модули gulp gulp-newer и gulp-data.
var gulp = require('gulp' )
, data = require('gulp-data' )
, newer = require('gulp-newer' )
, child_process = require('child_process')
;
gulp.task( 'gulpfile.js' , function() {
return gulp.src( 'sources/gulpfile.js' ) // source
.pipe( newer( '.' ) ) // check
.pipe( gulp.dest( '.' ) ) // write
.pipe( data( function(file) { // reboot
console.log('gulpfile.js changed! Restarting gulp...') ;
var t , args = process.argv ;
while ( args.shift().substr(-4) !== 'gulp' ) { t=args; }
child_process.spawn( 'gulp' , args , { stdio: 'inherit' } ) ;
return process.exit() ;
} ) )
;
} ) ;
Это работает следующим образом:
- Уловка 1: gulp-newer выполняет следующие каналы только в том случае, если исходный файл новее текущего. Таким образом мы убеждаемся, что нет цикла перезагрузки.
- Цикл while удаляет все до и включая команду gulp из командной строки, поэтому мы можем передать любые аргументы.
- child_process.spawn порождает новый процесс gulp, передающий ввод-вывод и ошибку родительскому процессу.
- Уловка 2: process.exit убивает текущий процесс. Однако процесс будет ждать смерти, пока дочерний процесс не завершится.
Есть много других способов вставить функцию перезапуска в пайпы. Я так или иначе использую gulp-data в каждом из моих gulpfiles. Не стесняйтесь комментировать собственное решение. :)
Я имел дело с той же проблемой, и решение в моем случае было на самом деле очень простым. Две вещи.
npm install nodemon -g
(или локально, если хотите)запустите с помощью cmd или создайте скрипт в таких пакетах:
"dev": "nodemon --watch gulpfile.js --exec gulp"
Просто введите
npm run dev
--watch
указывает файл, за которым нужно следить. --exec
говорит выполнить следующее в очереди, а gulp
является вашей задачей по умолчанию. Просто передайте аргумент, если вам нужна задача не по умолчанию.
Надеюсь, поможет.
РЕДАКТИРОВАТЬ: Сделать это модно ;) Теперь, хотя первая часть должна достичь того, что вы хотели, в моей настройке мне нужно было добавить немного больше, чтобы сделать ее действительно удобной для пользователя. Я хотел, чтобы
- Сначала откройте страницу.
- Найдите изменения в gulpfile.js и перезапустите gulp, если они есть.
- Глотайте его, так что следите за файлами, перестраивайте и перезагружайте
Если делать только то, что я сказал в первой части, то страница будет каждый раз открываться. Чтобы исправить это, создайте задачу gulp, которая откроет страницу. Как это :
gulp.task('open', function(){
return gulp
.src(config.buildDest + '/index.html')
.pipe(plugins.open({
uri: config.url
}));
Тогда в моих основных задачах у меня есть:
gulp.task('default', ['dev-open']);
gulp.task('dev-open', function(done){
plugins.sequence('build', 'connect', 'open', 'watch', done);
});
gulp.task('dev', function(done){
plugins.sequence('build', 'connect', 'watch', done);
});
Затем изменив ваши сценарии npm на
"dev": "gulp open & nodemon --watch gulpfile.js --watch webpack.config.js --exec gulp dev"
Даст вам именно то, что вы хотите. Сначала откройте страницу, а затем просто продолжайте перезагрузку. Кстати, для livereload я использую тот, который поставляется с подключением, который всегда использует один и тот же порт. Надеюсь, это сработает для вас, наслаждайтесь!
Вот еще одна версия кода перезагрузки @CaioToOn, которая больше соответствует обычной процедуре задачи Gulp. Это также не зависит от yargs
.
Требовать создание и инициализацию переменной процесса (yargs
не требуется):
var spawn = require('child_process').spawn;
var p;
Задача gulp по умолчанию будет генератором:
gulp.task('default', function() {
if(p) { p.kill(); }
// Note: The 'watch' is the new name of your normally-default gulp task. Substitute if needed.
p = spawn('gulp', ['watch'], {stdio: 'inherit'});
});
Ваша задача просмотра, вероятно, была вашей задачей глотка по умолчанию. Переименуйте его в watch
и добавьте gulp.watch()
для просмотра вашего gulpfile и запускайте задачу default
при изменениях:
gulp.task('watch', ['sass'], function () {
gulp.watch("scss/*.scss", ['sass']);
gulp.watch('gulpfile.js', ['default']);
});
Теперь просто запустите gulp
, и он автоматически перезагрузится, если вы измените gulpfile!
попробуйте этот код (только для платформы win32)
gulp.task('default', ['less', 'scripts', 'watch'], function(){
gulp.watch('./gulpfile.js').once('change' ,function(){
var p;
var childProcess = require('child_process');
if(process.platform === 'win32'){
if(p){
childProcess.exec('taskkill /PID' + p.id + ' /T /F', function(){});
p.kill();
}else{
p = childProcess.spawn(process.argv[0],[process.argv[1]],{stdio: 'inherit'});
}
}
});
});
connect.reload()
, вам нужно запустить connect.serverClose()
перед обработкой процесса. В противном случае порт не освобождается и выдает больше ошибок.
- person nazikus; 11.08.2016
Хорошее решение для Windows, которое также хорошо работает с исполнителем задач Visual Studio.
/// <binding ProjectOpened='auto-watchdog' />
const spawn = require('child-proc').spawn,
configPaths = ['Gulpconfig.js', 'bundleconfig.js'];
gulp.task('watchdog', function () {
// TODO: add other watches here
gulp.watch(configPaths, function () {
process.exit(0);
});
});
gulp.task('auto-watchdog', function () {
let p = null;
gulp.watch(configPaths, spawnChildren);
spawnChildren();
function spawnChildren() {
const args = ['watchdog', '--color'];
// kill previous spawned process
if (p) {
// You might want to trigger a build as well
args.unshift('build');
setTimeout(function () {
p.kill();
}, 1000);
}
// `spawn` a child `gulp` process linked to the parent `stdio`
p = spawn('gulp', args, { stdio: 'inherit' });
}
});
Основные изменения по сравнению с другими ответами:
- Использует child-proc, поскольку в Windows происходит сбой child_process.
- Сторожевой таймер завершает работу при изменении файлов, потому что в Windows вызов gulp заключен в пакетный сценарий. Уничтожение пакетного сценария не убьет сам gulp, что приведет к появлению нескольких часов с течением времени.
- Создание изменений: обычно изменение gulpfile также требует пересборки проекта.
Установите nodemon глобально: npm i -g nodemon
И добавьте в свой .bashrc (или .bash_profile или .profile) псевдоним:
alias gulp='nodemon --watch gulpfile.js --watch gulpfile.babel.js --quiet --exitcrash --exec gulp'
Это будет отслеживать изменения файлов gulpfile.js и gulpfile.babel.js. (см. Google)
P.S. Это может быть полезно для бесконечных задач (например, watch
), но не для однократных задач. Я имею в виду, что он использует часы, поэтому он продолжит процесс даже после выполнения задачи gulp. ;)
Вот короткая версия, которую легко понять, которую вы можете установить в качестве задачи по умолчанию, поэтому вам просто нужно ввести «gulp»:
gulp.task('watch', function() {
const restartingGulpProcessCmd = 'while true; do gulp watch2 --colors; done;';
const restartingGulpProcess = require('child_process').exec(restartingGulpProcessCmd);
restartingGulpProcess.stdout.pipe(process.stdout);
restartingGulpProcess.stderr.pipe(process.stderr);
});
gulp.task('watch2', function() {
gulp.watch(['config/**.js', 'webpack.config.js', './gulpfile.js'],
() => {
console.log('Config file changed. Quitting so gulp can be restarted.');
process.exit();
});
// Add your other watch and build commands here
}
gulp.task('default', ['watch']);
Установить gulp-restart
npm install gulp-restart
Этот код будет работать для вас.
var gulp = require('gulp');
var restart = require('gulp-restart');
gulp.task('watch', function() {
gulp.watch(['gulpfile.js'], restart);
})
он перезапустит gulp, где вы вносите изменения в gulpfile.js
Я потратил целый день, пытаясь заставить это работать на Windows/Gulp 4.0.2, и у меня (наконец-то) получилось...
Я использовал некоторые решения от людей на этой странице и на одной другой странице. В комментариях все есть...
Любые изменения в любой функции внутри allTasks повлияют на сохранение gulpfile.js (или других отслеживаемых файлов)...
Остались бесполезные комментарии и логи console.log, можете их удалить... ;)
const { gulp, watch, src, dest, series, parallel } = require("gulp");
const spawn = require('child_process').spawn;
// This function contains all that is necessary: start server, watch files...
const allTasks = function (callback) {
console.log('==========');
console.log('========== STARTING THE GULP DEFAULT TASK...');
console.log('========== USE CTRL+C TO STOP THE TASK');
console.log('==========');
startServer();
// other functions (watchers) here
// *** Thanks to Sebazzz ***
// Stop all on gulpfile.js change
watch('gulpfile.js', function (callback) {
callback(); // avoid "task didn't complete" error
process.exit();
});
callback(); // avoid "task didn't complete" error
}
// Restart allTasks
// ********************************************
// CALL GULPDEFAULT WITH THE GULP DEFAULT TASK:
// export.default = gulpDefault
// ********************************************
const gulpDefault = function (callback) {
let p = null;
watch('gulpfile.js', spawnChildren);
// *** Thanks to Sphinxxx: ***
// New behavior in gulp v4: The watcher function (spawnChildren()) is passed a callback argument
// which must be called after spawnChildren() is done, or else the auto-reload task
// never goes back to watching for further changes (i.e.the reload only works once).
spawnChildren(callback);
function spawnChildren(callback) {
/*
// This didn't do anything for me, with or without the delay,
// so I left it there, but commented it out, together with the console.logs...
// kill previous spawned process
if (p) {
// You might want to trigger a build as well
//args.unshift('build');
setTimeout(function () {
console.log('========== p.pid before kill: ' + p.pid); // a random number
console.log('========== p before kill: ' + p); // [object Object]
p.kill();
console.log('========== p.pid after kill: ' + p.pid); // the same random number
console.log('========== p after kill: ' + p); // still [object Object]
}, 1000);
}
*/
// `spawn` a child `gulp` process linked to the parent `stdio`
// ['watch'] is the task that calls the main function (allTasks):
// exports.watch = allTasks;
p = spawn('gulp', ['watch'], { stdio: 'inherit', shell: true });
// *** Thanks to people from: ***
// https://stackoverflow.com/questions/27688804/how-do-i-debug-error-spawn-enoent-on-node-js
// Prevent Error: spawn ENOENT
// by passing "shell: true" to the spawn options
callback(); // callback called - thanks to Sphinxxx
}
}
exports.default = gulpDefault;
exports.watch = allTasks;