grunt-contrib-watch
grunt-contrib-watch copied to clipboard
Let livereload not wait for certain watches
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.
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 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.
@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.
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.
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.
@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 Result is the same, I still see the content flash in the browser only after all unit tests finish executing.
@mzgol Thanks, marking as a bug. Will try and fix soon.
@shama Hey, what's the progress on a fix? :)
@mzgol Sorry nothing yet. It's marked as an ugly red bug so it will get fixed within the next release.
OK, thx.
I also confirm. @shama are there any fixes yet?
+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.
Any progress on this? It looks like the last mention was 4 months ago... would it help if someone submitted a pull request?
Yep, patches always welcomed :)
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.
+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.
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
}
}
}
Any update on this issue?
@yesman82 this doesn't work for what mzgol wants to do: fire livereload before running the tests
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!
}
}
}
}
any updates on this?
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.