javascriptgruntjsgrunt-contrib-watchnodemongrunt-concurrent

Infinite loop when running grunt-concurrent with 'nodemon' and 'watch' tasks


I am attempting to use the grunt-concurrent task to run grunt-nodemon to watch my js scripts and concurrently use watchto still concat and uglify my files when they change as well.

When I run grunt on the command line I get the following infinite loop:

Running "watch" task
Waiting...
Verifying property watch.concurrent.files exists in config...ERROR >> Unable to process task.
Warning: Required config property "watch.concurrent.files" missing.

The only way to stop this constant barrage of messages is to quit out of the command line.

Here is my gruntfile:

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
    dist: {
        src: [
            'public/js/libs/*.js',
        ],
        dest: 'public/js/build/production.js',
        }
    },
    uglify: {
        build: {
            src: 'public/js/build/production.js',
            dest: 'public/js/build/production.min.js'
        }
    },
    css: {
      files: ['css/*.scss'],
      tasks: ['sass'],
      options: {
          spawn: false,
      }
    },
    sass: {
    dist: {
        options: {
            style: 'compressed'
        },
        files: {
            'public/css/build/main.css': 'public/css/main.scss'
        }
      }
    },
    nodemon: {
      dev: {
        script: './start.js'
      }
    },
    watch: {
    scripts: {
        files: ['js/*.js'],
        tasks: ['concat','uglify'],
        options: {
            spawn: false,
        },
    },
    concurrent: {
        target: {
            tasks: ['nodemon', 'watch'],
            options: {
                logConcurrentOutput: true
            }
        }
    },
  }
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-nodemon');
grunt.loadNpmTasks('grunt-concurrent');
grunt.registerTask('default', ['concat','uglify','sass','watch','nodemon','concurrent:target']);
};

Here is my package.json:

{
  "name": "**** *****",
  "version": "1.0.0",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-concurrent": "^2.3.1",
    "grunt-contrib-concat": "^1.0.1",
    "grunt-contrib-imagemin": "^1.0.1",
    "grunt-contrib-sass": "^1.0.0",
    "grunt-contrib-uglify": "^2.3.0",
    "grunt-contrib-watch": "^1.0.0",
    "grunt-nodemon": "^0.4.2",
    "webpack-dev-server": "^2.9.7"
  },
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "nodemon ./start.js"
  },
  "author": "**** *******",
  "license": "ISC",
  "dependencies": {
    "cookie-parser": "^1.4.3",
    "dotenv": "^4.0.0",
    "express": "^4.16.2",
    "mongod": "^2.0.0",
    "mongoose": "^4.13.7",
    "nodemon": "^1.14.1",
    "normalize.css": "^6.0.0"
  }
}

EDIT: INFINITE LOOP SOLVED

I still don't think I have completely solved my issue, but I am one step closer...

I had a syntax error/omission in my watchtask:

    watch: {
    scripts: {
        files: ['js/*.js'],
        tasks: ['concat','uglify'],
        options: {
            spawn: false,
        },
    },

Should have included

watch: {
scripts: {
    files: ['js/*.js'],
    tasks: ['concat','uglify'],
    options: {
        spawn: false,
    },
},
css: {
      files: ['css/*.scss'],
      tasks: ['sass'],
      options: {
          spawn: false,
      },
    }
},

This was preventing my watch task from running correctly. I currently do NOT have the infinite loop anymore. Instead my command line renders this:

Running "concat:dist" (concat) task

Running "uglify:build" (uglify) task
>> 1 file created 797.64 kB → 378.58 kB

Running "sass:dist" (sass) task

Running "nodemon:dev" (nodemon) task
[nodemon] 1.14.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node ./start.js`
Express running → PORT 7777

It would appear that nodemon is running, but it doesn't say anything about my watch task at all, and when I change my SCSS file, nothing happens. I would obviously like grunt-concurrent to run BOTH my nodemon and watch tasks at the same time.

Should the command line be saying something different if it has executed successfully without any errors?

Thanks!


Solution

  • Removing nodemon and watch from grunt.registerTask code resolved the issue:

    grunt.registerTask('default', ['concat','uglify','sass','watch','nodemon','concurrent:target']);

    was running nodemon and watch as a default task and then attempting to run concurrent:target when just running concurrent:target would have run nodemon and watch concurrently anyway.

    Now the terminal renders:

    Running "concat:dist" (concat) task
    
    Running "uglify:build" (uglify) task
    >> 1 file created 797.64 kB → 378.58 kB
    
    Running "sass:dist" (sass) task
    
    Running "concurrent:target" (concurrent) task
        Running "watch" task
        Waiting...
        Running "nodemon:dev" (nodemon) task
        [nodemon] 1.14.1
        [nodemon] to restart at any time, enter `rs`
        [nodemon] watching: *.*
        [nodemon] starting `node ./start.js`
        Express running → PORT 7777
    

    Which looks correct!

    The new, corrected Gruntfile looks like this:

    module.exports = function(grunt) {
      grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        concat: {
        dist: {
            src: [
                'public/js/libs/*.js',
            ],
            dest: 'public/js/build/production.js',
            }
        },
        uglify: {
            build: {
                src: 'public/js/build/production.js',
                dest: 'public/js/build/production.min.js'
            }
        },
        sass: {
        dist: {
            options: {
                style: 'compressed'
            },
            files: {
                'public/css/build/main.css': 'public/css/main.scss'
            }
          }
        },
        concurrent: {
            target: {
                tasks: ['nodemon', 'watch'],
                options: {
                    logConcurrentOutput: true
                }
            }
        },
        watch: {
        scripts: {
            files: ['./public/js/*.js'],
            tasks: ['concat','uglify'],
            options: {
                spawn: false,
            },
        },
        css: {
              files: ['./public/css/*.scss'],
              tasks: ['sass'],
              options: {
                  spawn: false,
              },
            }
        },
        nodemon: {
          dev: {
            script: './start.js'
          }
        },
    });
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-nodemon');
    grunt.loadNpmTasks('grunt-concurrent');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.registerTask('default', ['concat','uglify','sass','concurrent:target']);
    
    };