gruntjsgrunt-contrib-watchgrunt-concurrent

Grunt: `contrib-watch` Fire livereload event after `grunt-nodemon` has restarted when server-side `.coffee` files are compiled


I've been having an issue with Grunt.js and a few plugins, notably: grunt-contrib-watch, grunt-nodemon and grunt-contrib-coffee. I've been trying to figure this out for two days now but I don't think my knowledge of Grunt is sufficient to solve it at this point.

The problem I'm experiencing is simply that I want my server-side .coffee files to compile and then have nodemon restart the server and THEN only have livereload work. Right now, Livereload works as intended for everything but server-side coffee files. contrib-watch detects the change, runs coffee and fires off a livereload event, but then nodemon restarts.

Is there a way to get nodemon to restart before the page reloads so that what I see on the screen is up-to-date with what's going on in my server-side code?

I've been presented with the option of just running nodemon in a separate terminal tab, but I'm on Windows and would much prefer to keep one terminal running for this purpose and is the whole reason I'm using grunt-concurrent.

Here's my Gruntfile, it's quite early in it's stages (as I try to figure all this out). If you would prefer I compile it to JavaScript, then just leave a comment and request so, I will be happy to.

module.exports = (grunt) ->

  # configuration
  grunt.initConfig
    pkg: grunt.file.readJSON 'package.json'

    # watch task
    watch:
      css:
        files: ['src/assets/styles/**/*.styl']
        tasks: ['stylus']
        options:
          livereload: true
      coffee:
        files: ['src/**/*.coffee']
        tasks: ['coffee']
      js:
        files: ['**/*.js']
        options:
          livereload: true
      jade:
        files: ['views/**/*.jade']
        options:
          livereload: true

    # compile coffeescript to javascript
    coffee:
      compile:
        options:
          sourceMap: true
        files: [
          expand: true
          cwd: 'src/'
          src: ['**/*.coffee']
          dest: ''
          ext: '.js'
        ]

    # compile stylus to css
    stylus:
      compile:
        files: [
          expand: true
          cwd: 'src/assets/styles/'
          src: ['**/*.styl']
          dest: 'assets/styles/'
          ext: '.css'
        ]

    # run server
    nodemon:
      dev:
        options:
          file: 'server.js'
          watchedExtensions: ['js', 'json']
          ignoredFiles: [
            'assets/**',
            'node_modules/**',
            '**/.js.map'
          ]

    # run tasks concurrently for fast builds
    concurrent:
      first:
        tasks: ['coffee', 'stylus']
        options:
          logConcurrentOutput: true
      second:
        tasks: ['nodemon', 'watch']
        options:
          logConcurrentOutput: true

  # load dependencies
  require('load-grunt-tasks') grunt

  # register tasks
  grunt.registerTask 'default', [
    'concurrent:first',
    'concurrent:second'
  ]

Solution

  • I've not used this myself but I came across it a while ago: grunt-rerun. Used in combination with a watch task you can pause a long running task such as express (but probably would work with nodemon as well), run some tasks, then start the task again. The sample config looks like so:

    grunt.initConfig({
      watch: {
          dev: {
            files: ['server/*.js'],
    
            //Note the :go flag used for sending the reload message to the rerun server
            tasks: ['clean','rerun:dev:express:go']
          },
        },
        express: {
            dev: {
                options: {
                    port: 3000,
                    bases: ['/public'],
                    keepalive: true,
                    server: path.resolve('./server/app.js')
                }
            }
        },
        // Configuration to be run (and then tested).
        rerun: {
          dev: {
            options: {
              tasks: ['express']
            },
          },
        }
    })
    

    https://npmjs.org/package/grunt-rerun

    I'm not entirely sure about the live reload thing. My guess would be because it shuts down the process, by spawning a new one it would load the page afresh, but I haven't used this personally so I'm not sure.

    The second alternative is yes, to use a command prompt that supports multiple tabs, such as Console. I'm a Mac user and so I use iTerm 2 which has multiple panes; most of the time I have four open per project, for watch, testem, a php server and a shell for everything else. You may find that this is a lot quicker and a lot less hassle.

    Just a quick note on Coffeescript, a lot of JavaScript developers don't use it, so to get a wider audience to understand your source code, it may be good practice to compile coffee into js before you post your question.