14

Short of it: started using Gulp recently (convert from Grunt), and am trying to use both Gulp's default watch task (not gulp-watch from npm) for SASS/JS/HTML and gulp-nodemon (from npm) to restart an Express server upon changes. When running just gulp watch, it works fine; and when running gulp server (for nodemon) that works fine. However, using both together (shown below in the configuration of the default task), the watch stuff isn't working. The task is running, and on the CLI gulp shows 'Starting' and 'Finished' for the watch tasks, but the files don't update.

Relevant task configurations:

Concat javascript:

    gulp.task('js:app', function(){
        return gulp.src([
            pathSource('js/application/modules/**/*.js'),
            pathSource('js/application/_main.js')
        ])
        .pipe(concat('application.js'))
        .pipe(gulp.dest('./build/assets/js')).on('error', utils.log);
    });

Nodemon, restart on changes to express app:

    gulp.task('express', function(){
        return nodemon({script:'server.js', ext:'js', cwd: __dirname + '/express', legacyWatch: true})
        .on('restart', function(){
            //gulp.run('watch'); // doesn't work :(
        });
});

Watch javascript changes, and run js:app for concat'ing.

    gulp.task('watch', function(){
      gulp.watch(pathSource('js/application/**/*.js'), ['js:app']);
    });

Default task, to initialize gulp watch and nodemon simultaneously:

    gulp.task('default', ['watch', 'express']);

If anyone has any ideas, thanks in advance!

jiveTurkey
  • 689
  • 3
  • 7
  • 17

2 Answers2

16

gulp.run calls have been deprecated, so I'd try a different approach. Since you're already using gulp, may I suggest giving gulp-nodemon a try?

As per gulp-nodemon documentation, you can pass it an array of tasks to execute:

UPDATE: Here's the full gulpfile.js file, together with a working sample on github.

'use strict';

// Main dependencies and plugins
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var nodemon = require('gulp-nodemon');

var assets = 'assets/js/**/*.js';
var publicDir = 'public/javascripts';

// Lint Task
gulp.task('lint', function () {
  return gulp.src(assets)
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'));
});

// Concatenate and minify all JS files
gulp.task('scripts', function () {
  return gulp.src(assets)
    .pipe(concat('global.js'))
    .pipe(gulp.dest(publicDir))
    .pipe(rename('global.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(publicDir));
});

// Watch Files For Changes
gulp.task('watch', function () {
  gulp.watch(assets, ['lint', 'scripts']);
});

gulp.task('demon', function () {
  nodemon({
    script: 'server.js',
    ext: 'js',
    env: {
      'NODE_ENV': 'development'
    }
  })
    .on('start', ['watch'])
    .on('change', ['watch'])
    .on('restart', function () {
      console.log('restarted!');
    });
});

// Default Task
gulp.task('default', ['demon']);

This way, you spawn the watch task upon nodemon's start and ensure that the watch task is again triggered whenever nodemon restarts your app.

EDIT: seems you should be calling the on-change event from gulp-nodemon, which will handle compile tasks before the restart event triggers.

EDIT: It seems nodemon's on('change', callback) is removed from their API

Gaston
  • 840
  • 1
  • 18
  • 27
  • gaston - the setup i'm using is already w/ gulp-nodemon actually; however, i didn't configure it so that it would restart the watch task on change. i'll give it a go and let ya know. thx! – jiveTurkey May 17 '14 at 00:29
  • so wasn't able to get it to work that way. what's confusing me: if I run the nodemon task like so: `gulp.task('demon', ['watch'], function(){ nodemon({...}) })`, both nodemon AND the watch task will execute and show output on a file changing - but the changes from the watch task aren't written to the appropriate files. like the task is run, but its not piping the changes to disk. – jiveTurkey May 17 '14 at 01:03
  • 1
    @jiveTurkey I've updated my answer with the full gulpfile and left a working [github sample](https://github.com/gfestari/gulp-sample). Basically, this will start `nodemon` and link it with a `gulp-watch` task to monitor file changes. Let me know how it goes ;) – Gaston May 17 '14 at 16:07
  • Thanks for your answer, Gaston. This worked like a charm and really helped me! In my gulpfile.js I removed `.on('change', ['watch'])` because the `watch` task was running twice, once right before the change and once again after the server restarted. – jClark May 23 '14 at 08:17
  • @Gaston - thx again for the help, approach above didn't solve the issue unfortunately (although it put me on the right track :). It seems that running either a 'watch' task or a 'nodemon' task independently works fine. However, if the nodemon configuration has `{cwd: 'something_relative_here'}`, that _will influence the paths used by the watch tasks_. You'd think that they'd be completely isolated, but for some reason the `cwd` property in nodemon will influence paths in gulp.watch(...) configurations. Solution was to make paths absolute. Not ideal. Will post explanation in full below. – jiveTurkey Jun 04 '14 at 00:49
  • @jiveTurkey Glad to hear you got it sorted out... and that I was of help somehow :D – Gaston Jun 04 '14 at 01:11
4

FWIW, it seems that using the cwd parameter on gulp-nodemon's configuration actually sets the entire gulp cwd to that directory. This means future tasks will be executed in the wrong directory.

I had this problem when running gulp watch tasks on my frontend server at the same time as nodemon tasks on my backend server (in the same gulpfile), there was a race condition wherein if the nodemon command was executed first, the frontend stuff would actually build into (Home)/backend/frontend instead of (Home)/frontend, and everything would go pearshaped from there.

I found that using watch and script params on gulp-nodemon worked around this (although it still looks like nodemon is watching my entire project for changes rather than the built backend directory).

pfooti
  • 2,605
  • 2
  • 24
  • 37