如何在每次Gulpfile更改后重新启动Gulp?

时间:2014-04-05 20:54:42

标签: javascript node.js workflow gulp gulp-watch

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

14 个答案:

答案 0 :(得分:59)

您可以为taskspawn another gulp child_process gulp.watch创建一个gulpfile.js

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查看日志。

答案 1 :(得分:37)

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

你可以简单地用gulper替换gulp。

$ gulper <task-name>

答案 2 :(得分:11)

我为此目的使用了一个小的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

答案 3 :(得分:9)

我在Caio Cunha的回答中得到了一堆EADDRINUSE错误。我的gulpfile打开了一个包含connectLiveReload的本地网络服务器。看起来新的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

答案 4 :(得分: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);
  });
});

答案 5 :(得分:2)

我知道这是一个非常古老的问题,但这是对谷歌的最高评论,因此仍然非常相关。

如果您的源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 会杀死当前进程。但是,该过程将等待直到子进程完成为止。

还有许多其他方法可以将重启功能插入管道。 无论如何,我恰巧在我的每个gulpfiles中使用gulp-data。随意评论您自己的解决方案。 :)

答案 6 :(得分: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'});
});

您的监视任务可能是您的默认gulp任务。将其重命名为watch并添加gulp.watch()以观察您的gulpfile并对更改运行default任务:

gulp.task('watch', ['sass'], function () {
  gulp.watch("scss/*.scss", ['sass']);
  gulp.watch('gulpfile.js', ['default']);
});

现在,只需运行gulp,如果更改了gulp文件,它将自动重新加载!

答案 7 :(得分: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'});
            }
        }
    });
});

答案 8 :(得分:1)

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

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

    "dev": "nodemon --watch gulpfile.js --exec gulp"
    
  3. 只是输入npm run dev

  4. --watch指定要关注的文件。 --exec表示执行下一行,gulp是您的默认任务。如果你想要非默认任务,只需传入参数。

    希望它有所帮助。

    编辑:让它看起来很棒;) 现在,虽然第一部分应该实现你所追求的目标,但在我的设置中,我需要添加更多内容才能使其真正成为用户朋友。我想要的是

    1. 首先打开页面。
    2. 查找gulpfile.js中的更改,如果有任何
    3. ,请重新启动gulp
    4. gulp up所以密切关注文件,重建和热重载
    5. 如果您只做我在第一部分中所说的内容,它每次都会打开页面。要修复它,请创建一个打开页面的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"
      

      会准确地给你你想要的东西。首先打开页面然后只是保持实时重新加载。 btw for livereload我使用的是随附的连接,它总是使用相同的端口。希望它适合你,享受!

答案 9 :(得分: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的变化。 (见Google

P.S。这对于无休止的任务(如watch)有帮助,但对单次运行任务则无效。我的意思是它使用手表,所以即使在gulp任务完成后它也会继续处理。 ;)

答案 10 :(得分: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调用包含在批处理脚本中。杀死批处理脚本不会导致吞噬本身,导致多个手表随着时间的推移而产生。
  • 以变化为基础:通常gulpfile更改也可以保证重建项目。

答案 11 :(得分: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']);

答案 12 :(得分:0)

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

答案 13 :(得分: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;