14
votes

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!

2

2 Answers

16
votes

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

4
votes

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).