我正在开发一个Gulpfile
. 可以让它一改变就重新启动吗?我正在使用 CoffeeScript 开发它。保存更改时可以Gulp
观看Gulpfile.coffee
以重新启动吗?
14 回答
您可以task
为gulp.watch
另一个gulp child_processgulpfile.js
创建一个。spawn
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
查看日志。
我创建了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 外壳脚本:
# watch.sh
while true; do
gulp watch;
done;
视窗版本:watch.bat
@echo off
:label
cmd /c gulp watch
goto label
EADDRINUSE
在 Caio Cunha 的回答中,我遇到了一堆错误。我的 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。
另一个解决方案是刷新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);
});
});
我知道这是一个非常古老的问题,但它是谷歌的顶级评论,所以仍然非常相关。
如果您的源 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杀死当前进程。但是,该进程将等待死亡,直到子进程完成。
还有许多其他方法可以将重启功能插入管道。无论如何,我只是碰巧在我的每个 gulpfile 中都使用了 gulp-data。随意评论您自己的解决方案。:)
我一直在处理同样的问题,我的解决方案实际上非常简单。两件事情。
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,我使用 connect 附带的那个,它总是使用相同的端口。希望它对你有用,享受!
这是@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,它将自动重新加载!
全局安装 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 的变化。(见谷歌)
PS这对无休止的任务(例如watch
)很有帮助,但对单次运行的任务没有帮助。我的意思是它使用 watch 所以即使在 gulp 任务完成后它也会继续处理。;)
试试这个代码(仅限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'});
}
}
});
});
适用于 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 因为 child_process 在 Windows 上失败。
- 看门狗会在文件更改时自行退出,因为在 Windows 中,gulp 调用包含在批处理脚本中。杀死批处理脚本不会杀死 gulp 本身,从而导致随着时间的推移产生多个手表。
- Build on change:通常 gulpfile 更改也需要重建项目。
我花了一整天的时间试图在Windows / Gulp 4.0.2上完成这项工作,我(终于)做到了......
我在此页面和另一页面上使用了人们的一些解决方案。评论里都有啊……
“allTasks”中任何函数的任何更改都将在 gulpfile.js(或其他监视文件)保存时生效...
有一些无用的评论和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”:
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);
})
它会在你对 gulpfile.js 进行更改的地方重新启动 gulp