【发布时间】:2014-05-18 04:14:46
【问题描述】:
我正在开发Gulpfile。可以让它一改变就重新启动吗?我正在使用 CoffeeScript 开发它。 Gulp 是否可以监视 Gulpfile.coffee 以便在保存更改时重新启动?
【问题讨论】:
标签: javascript node.js workflow gulp gulp-watch
我正在开发Gulpfile。可以让它一改变就重新启动吗?我正在使用 CoffeeScript 开发它。 Gulp 是否可以监视 Gulpfile.coffee 以便在保存更改时重新启动?
【问题讨论】:
标签: javascript node.js workflow gulp gulp-watch
您可以创建一个task,它将gulp.watch 用于gulpfile.js 和简单的spawn another 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 一样运行它,否则你可能会得到一个fork-bomb 以递归方式启动默认任务。
2014-07-29 11:48 gulp[74366] (CarbonCore.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)),例如localhost:3000 使用 BrowserSync 时端口号递增
我创建了gulper,它是 gulp.js cli 包装器,用于在 gulpfile 更改时重新启动 gulp。
您可以简单地将 gulp 替换为 gulper。
$ gulper <task-name>
【讨论】:
为此,我使用了一个小的 shell 脚本。这也适用于 Windows。
按Ctrl+C 停止脚本。
// gulpfile.js
gulp.task('watch', function() {
gulp.watch('gulpfile.js', process.exit);
});
Bash shell 脚本:
# watch.sh
while true; do
gulp watch;
done;
Windows 版本:watch.bat
@echo off
:label
cmd /c gulp watch
goto label
【讨论】:
我在 Caio Cunha 的回答中遇到了一堆 EADDRINUSE 错误。我的 gulpfile 使用 connect 和 LiveReload 打开本地网络服务器。在旧进程被杀死之前,新的 gulp 进程似乎与旧进程短暂共存,因此即将死亡的进程仍在使用这些端口。
这是一个解决共存问题的类似解决方案,(主要基于this):
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()
另一个解决方案是刷新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 否则你可能会有内存泄漏
end它
我知道这是一个非常古老的问题,但它是 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() ;
} ) )
;
} ) ;
它是这样工作的:
还有许多其他方法可以将重启功能插入管道。 无论如何,我只是碰巧在我的每个 gulpfile 中都使用了 gulp-data。随意评论您自己的解决方案。 :)
【讨论】:
我一直在处理同样的问题,我的解决方案实际上非常简单。两件事。
npm install nodemon -g(如果您愿意,也可以在本地)使用 cmd 运行或在包中创建脚本,如下所示:
"dev": "nodemon --watch gulpfile.js --exec gulp"
只需输入npm run dev
--watch 指定要关注的文件。 --exec 表示执行下一行,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,我使用 connect 附带的那个,它总是使用相同的端口。希望它对你有用,享受吧!
【讨论】:
nodemon 添加到 optionalDependencies 和 2)在自述文件中提及
这是@CaioToOn 的另一个版本的重载代码,它更符合正常的 Gulp 任务过程。它也不依赖于yargs。
需要生成并初始化进程变量(不需要yargs):
var spawn = require('child_process').spawn;
var p;
默认的 gulp 任务是 spawner:
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 并添加 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()。否则端口不会被释放并引发更多错误。
适用于 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' });
}
});
与其他答案相比的主要变化:
【讨论】:
全局安装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)可能会有所帮助,但对于单次运行的任务则无济于事。我的意思是它使用 watch 所以即使在 gulp 任务完成后它也会继续处理。 ;)
【讨论】:
nodemon添加到package.json中的"optionalDependencies",在package.json的"scripts"中包含"dev":"nodemon --watch gulpfile.js --exec gulp dev",最后在项目README中提及。
这是一个简单易懂的简短版本,您可以将其设置为默认任务,因此您只需键入“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']);
【讨论】:
我花了一整天的时间尝试在 Windows / Gulp 4.0.2 上完成这项工作,我(终于)成功了...
我使用了本页和另一页上人们提供的一些解决方案。这些都在 cmets 中......
“allTasks”内任何函数的任何更改都会在 gulpfile.js(或其他监视的文件)保存时生效...
还有一些没用的 cmets 和 console.logs,请随意删除它们... ;)
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;
【讨论】:
安装 gulp-restart
npm install gulp-restart
此代码对您有用。
var gulp = require('gulp');
var restart = require('gulp-restart');
gulp.task('watch', function() {
gulp.watch(['gulpfile.js'], restart);
})
它会在你对 gulpfile.js 进行更改的地方重新启动 gulp
【讨论】: