66

我正在开发一个Gulpfile. 可以让它一改变就重新启动吗?我正在使用 CoffeeScript 开发它。保存更改时可以Gulp观看Gulpfile.coffee以重新启动吗?

4

14 回答 14

60

您可以taskgulp.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.jstouch a.css查看日志。

于 2014-04-06T15:56:43.760 回答
42

我创建了gulper,它是 gulp.js cli 包装器,用于在 gulpfile 更改时重新启动 gulp。

您可以简单地将 gulp 替换为 gulper。

$ gulper <task-name>
于 2015-01-28T04:13:01.767 回答
12

为此,我使用了一个小的 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
于 2015-03-11T14:46:15.980 回答
9

EADDRINUSE在 Caio Cunha 的回答中,我遇到了一堆错误。我的 gulpfile 使用connectLiveReload打开本地网络服务器。在旧进程被杀死之前,新的 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

于 2014-12-15T05:36:39.807 回答
3

另一个解决方案是刷新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);
  });
});
于 2014-09-18T19:23:52.847 回答
3

我知道这是一个非常古老的问题,但它是谷歌的顶级评论,所以仍然非常相关。

如果您的源 gulpfile.js 位于与正在使用的目录不同的目录中,这是一种更简单的方法。(这很重要!)它使用 gulp 模块gulp-newergulp-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。随意评论您自己的解决方案。:)

于 2016-11-12T03:00:22.717 回答
3

我一直在处理同样的问题,我的解决方案实际上非常简单。两件事情。

  1. npm install nodemon -g(或者如果您愿意,也可以在本地)
  2. 使用 cmd 运行或在包中创建脚本,如下所示:

    "dev": "nodemon --watch gulpfile.js --exec gulp"
    
  3. 公正的类型npm run dev

--watch指定要关注的文件。--exec说在行中执行下一个并且gulp是您的默认任务。如果您想要非默认任务,只需传入参数。

希望能帮助到你。

编辑:让它变得花哨;)现在虽然第一部分应该实现您所追求的,但在我的设置中,我需要添加更多内容以使其成为真正的用户朋友。我想要的是

  1. 首先打开页面。
  2. 查找 gulpfile.js 中的更改,如果有任何更改,请重新启动 gulp
  3. 吞下它,以便密切关注文件、重建和热重载

如果你只做我在第一部分所说的,它每次都会打开页面。要修复它,请创建一个将打开页面的 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 附带的那个,它总是使用相同的端口。希望它对你有用,享受!

于 2016-06-06T10:10:24.700 回答
1

这是@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,它将自动重新加载!

于 2014-10-21T06:35:11.727 回答
1

全局安装 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 任务完成后它也会继续处理。;)

于 2016-11-14T23:27:48.760 回答
1

试试这个代码(仅限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'});
            }
        }
    });
});
于 2016-05-09T13:13:26.080 回答
1

适用于 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 更改也需要重建项目。
于 2017-01-25T17:48:18.753 回答
0

我花了一整天的时间试图在Windows / Gulp 4.0.2上完成这项工作,我(终于)做到了......

我在此页面和另一页面上使用了人们的一些解决方案。评论里都有啊……

“allTask​​s”中任何函数的任何更改都将在 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;
于 2021-02-11T20:00:34.297 回答
0

这是一个易于理解的简短版本,您可以将其设置为默认任务,因此您只需键入“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']);
于 2017-08-26T17:24:54.350 回答
-1

安装 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

于 2017-09-25T09:07:21.867 回答