Resolving LiveReload Conflicts in Grunt

Grunt is an excellent automation tool and part of the Yeoman toolset. It has this ridiculously cool feature that allows you to watch files for changes and then tell every browser looking at your webpages to refresh — mobile, tablet, desktop, whatever — and it does this without browser extensions. It’s pretty speccy.

There’s a problem though: if your HTML, CSS and JS is all generated from HAML, SASS and Coffeescript like me, it doesn’t work like you’d expect it to:


# Examples in Coffeescript, that's how I roll.

  grunt.initConfig {
    watch:
      livereload:
        files: [
          'src/example/**/*.{haml|coffee|sass}'
          'www/example/**/*.{html|js|css}'
        ]
        tasks: ['coffee', 'compass', 'hamlpy', 'livereload']
  }

Rather than compiling the Coffeescript, SASS and HAML, followed by a LiveReload, the watch event doesn’t pick up the changes to the HTML, CSS and Javascript so that reload never happens. Makes sense really, it’s not watching during the task run so it misses it.

You can’t run two watch tasks concurrently though, unless you open another terminal session. If you want to keep it all in one process, you can do this:


mm = require 'minimatch'

  grunt.initConfig {
    watch:
      livereload:
        files: [
          'src/example/**/*.{haml|coffee|sass}'
          'www/example/**/*.{html|js|css}'
        ]
        tasks: ['reloadDispatcher:example']
    reloadDispatcher:
      example:
        "**/*.haml" : ['hamlpy']
        "**/*.sass" : ['compass']
        "**/*.coffee" : ['coffee']
        "**/*.{html,css,js}" : ['livereload']
  }

  grunt.registerMultiTask 'reloadDispatcher', 'Run tasks based on extensions.', () ->
    for pattern, tasks of this.data
      if grunt.regarde.changed.some mm.filter pattern
        grunt.task.run tasks

With this new task, what it’s doing is checking the list of files changed that the watcher (grunt.regarde) detected against your patterns in the config, and then for any matches it runs the appropriate tasks. Dunno how it will behave in bigger projects but that’s enough experimentation for now.

Leave a comment