grunt-contrib-watch icon indicating copy to clipboard operation
grunt-contrib-watch copied to clipboard

Let livereload not wait for certain watches

Open mgol opened this issue 12 years ago • 22 comments

I use grunt-contrib-watch together with the grunt-karma task. Unfortunately, the watch task waits for all watches to finish executing which is painfully slow with lots of unit tests. I'd like the livereload to not wait for this particular task to finish as this is not a pre-processor and it doesn't influence what's going to the browser.

Preferably, watches should have option to set a flag preprocessor (by default true). When set to false, livereload should not wait for this watch task to finish.

mgol avatar Aug 19 '13 14:08 mgol

livereload should be triggered upon each task run completed. Meaning if broken up into multiple targets, it should fire upon the completion of each target to offer this level of control. So maybe it is just a matter of breaking out the slow tasks into separate targets?

shama avatar Aug 19 '13 16:08 shama

@shama If I add multiple targets with the same files, it'll only trigger one task, so that doesn't seem to be an option.

Ideally you'd be able to specify when to fire livereload manually. That way you can say something like:

myTask: {
    files: ['....'],
    tasks: ['coffee', 'ngtemplates', 'watch:myTask:livereload', 'karma']
}

Where watch:myTask:livereload triggers the livereload. Having livereload in grunt-contrib-watch is awesome, but sometimes it's slightly too coarse-grained.

This can be perfectly compatible with current behavior if you change grunt-contrib-watch to still fire livereload automatically (when configured) if the watch:myTask:livereload wasn't called.

rubenv avatar Aug 20 '13 13:08 rubenv

@shama, I tested it and I can confirm the issue. There are several other tasks executed (in particular, the unit tests) before livereload is executed.

mik01aj avatar Aug 20 '13 14:08 mik01aj

We could add another task that simply triggers the livereload. Although I think I would prefer to add an API to this proposal: #156 instead. Where you could:

watch: {
  tasks: function() {
    this.livereload(['file/fed/to/livereload/server.js']);
  }
}

Then those wanting more advanced control can specify how the task runs and exactly when it live reloads.

I also do see the issue where it waits until the end of all tasks to trigger the livereload. I'll see what I can do to fix that.

@rubenv Make sure you're using the latest version of the watch task, it should trigger multiple target tasks if they have cross over files.

shama avatar Aug 20 '13 16:08 shama

I confirm what @mik01aj says: I don't have all tasks to put in the list on the same target, I have sth like:

grunt.initConfig({
    karma: {
        backgroundUnit: {
            background: true,
            browsers: ['Chrome'],
            configFile: 'karma.conf.js',
            runnerPort: 9999,
            singleRun: false,
        },
    },

    watch: {
        options: {
            livereload: true,
        },
        jshint: {
            files: ['app/**/*.js'],
            tasks: ['jshint'],
        },
        karma: {
            files: [
                'karma*.conf.js',
                'app/**/*.js',
            ],
            tasks: ['karma:backgroundUnit:run'],
        },
        livereload: {
            files: ['app/**/*.js'],
            tasks: [],
        },
    },

    // configuration continues...
});

and if I modify any JS file, the result is that I first wait for jsHint to finish, then for all unit tests to be executed by Karma and only then I see the browser got updated files (because I see short flash of content).

I use grunt-contrib-watch version 0.5.2.

mgol avatar Aug 20 '13 17:08 mgol

@mzgol What if you update it to this:

        watch: {
            jshint: {
                files: ['app/**/*.js'],
                tasks: ['jshint'],
                options: {
                    livereload: true,
                },
            },
            karma: {
                files: [
                    'karma*.conf.js',
                    'app/**/*.js',
                ],
                tasks: ['karma:backgroundUnit:run'],
            },
        },

Will it livereload after jshint finishes or does it wait for jshint and karma to finish?

shama avatar Aug 20 '13 17:08 shama

@shama Result is the same, I still see the content flash in the browser only after all unit tests finish executing.

mgol avatar Aug 20 '13 17:08 mgol

@mzgol Thanks, marking as a bug. Will try and fix soon.

shama avatar Aug 20 '13 17:08 shama

@shama Hey, what's the progress on a fix? :)

mgol avatar Sep 11 '13 10:09 mgol

@mzgol Sorry nothing yet. It's marked as an ugly red bug so it will get fixed within the next release.

shama avatar Sep 11 '13 16:09 shama

OK, thx.

mgol avatar Sep 11 '13 18:09 mgol

I also confirm. @shama are there any fixes yet?

jrencz avatar Sep 25 '13 12:09 jrencz

+1 would love this feature to be fixed. Our tests take around 3 seconds to process, would like to reload the browser during those tests.

joemcelroy avatar Dec 19 '13 12:12 joemcelroy

Any progress on this? It looks like the last mention was 4 months ago... would it help if someone submitted a pull request?

tysoncadenhead avatar Jan 22 '14 19:01 tysoncadenhead

Yep, patches always welcomed :)

shama avatar Jan 22 '14 19:01 shama

Any progress on this as of late? I just ran into this as well and thankfully came across this issue instead of opening a new one.

seiyria avatar Aug 12 '14 18:08 seiyria

+1, ran into this at work... tried to submit a pull request, but got lost in trying to write a failing test for the problem and so didn't get very far. (I can only justify spending so much time on open-source projects at work) The problem is definitely in tasks/lib/taskrun.js at line 104:

// Trigger livereload if necessary
if (this.livereload && (this.livereloadOnError || !taskFailed)) {
  this.livereload.trigger(Object.keys(this.changedFiles));
  this.changedFiles = Object.create(null);
}

That code is currently in the TaskRun.prototype.complete method, but it probably should be near the end of TaskRun.prototype.run.

dallonf avatar Sep 11 '14 20:09 dallonf

Use grunt-wait (https://github.com/Bartvds/grunt-wait) and add it as a task to the watch config. It will first run the task and then do the live reload.

watch: {
  options: {
    livereload: true
  },
  php: {
    files: [
      'application/views/**/*.php',
      'application/controllers/**/*.php'
    ],
    tasks: ['wait:one']
  }
},
wait: {
  one: {
    options: {
      delay: 1000
    }
  }
}

patrickschaper avatar Sep 29 '14 13:09 patrickschaper

Any update on this issue?

@yesman82 this doesn't work for what mzgol wants to do: fire livereload before running the tests

ValentinH avatar Jan 29 '15 09:01 ValentinH

This is temporary solution, that works for me:

Install Livereload server:
$ npm install tiny-lr --save-dev
Define livereload task in Gruntfile.js:
var lrserver = require('tiny-lr')();

try {
    lrserver.listen(35729, function() {
        console.log('Livereload Server Started');
    });
} catch(e) {
    console.log('Error during starting Livereload Server');
}

grunt.registerTask('livereload', function() {
    lrserver.changed({body:{files:['index.html']}}); // It's really no metter what's changed
});
Add livereload task in watch config:
grunt.initConfig({
    watch: {
        karma: {
            files: [
                'src/js/**/*.js',
                'src/tests/**/*.test.js',
            ],
            tasks: ['livereload', 'karma:run'],
            options: {
                spawn: false // It's important!
            }
        }
    }
}

lasekio avatar Jan 30 '15 10:01 lasekio

any updates on this?

Zeragamba avatar Mar 17 '15 03:03 Zeragamba

The suggested solution from @laskos is not complete. This assumes that a full reload is what's wanted. However with CSS changes can be injected by livereload, without a full reload, making development much quicker when styling things up.

The only implementation I've been able to get working is to have two grunt process running.

  • One running the dev server using contrib-watch, which in my case complies sass, coffeescript & js templates with livereload.
  • The other to run tests if my spec files change.

Infact if you're using Karma you can just run karma standalone without grunt using its autoWatch feature.

raldred avatar Aug 07 '15 14:08 raldred