In learning how to use grunt, I am trying to make a simple coffee-script watcher/compiler. The problem is, if I tell the watch
task to watch several files, and
In this issue, Kyle Robinson suggests using the watch
event. It's very important to set watch task nospawn
property to true
to make it work. I modified his solution to selectively run the tasks:
grunt.event.on('watch', function(action, filepath) {
if (minimatch(filepath, grunt.config('watch.stylesheets.files'))) {
grunt.config('compass.dist.options.specify', [filepath]);
}
if (minimatch(filepath, grunt.config('watch.scripts.files'))) {
var uglifySrc = filepath.replace(grunt.config('uglify.dist.cwd'), '');
grunt.config('jshint.dist.src', [filepath]);
grunt.config('uglify.dist.src', [uglifySrc]);
}
});
Here is the complete solution: https://gist.github.com/luissquall/5408257
The task grunt-contrib-watch now supports this.
https://npmjs.org/package/grunt-contrib-watch -> look for "Compiling Files As Needed"
grunt.initConfig({
watch: {
scripts: {
files: ['lib/*.js'],
tasks: ['jshint'],
options: {
nospawn: true,
},
},
},
jshint: {
all: ['lib/*.js'],
},
});
// on watch events configure jshint:all to only run on changed file
grunt.event.on('watch', function(action, filepath) {
grunt.config(['jshint', 'all'], filepath);
});
This should prevent the tasks from compiling all files every time when something changes.
None of these answers worked very well for me. Here is my solution if anyone is interested (I know I'm a little late in replying to this question).
https://gist.github.com/ryansmith94/8569178
I got this working when compiling my less files. You should be able to mess with this configuration a little bit to git it working with the coffeescript plugin. The portion of interest is the grunt.event.on('watch', ...)
. In this event handler I'm updating the files
property in the less command to only contain the changed file.
path = require('path');
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
less: {
development: {
options: {
paths: ["./library/less"],
},
files: [
{ src: "./library/less/bootstrap.less", dest: "./library/css/bootstrap.css"},
{ src: "./library/less/app.less", dest: "./library/css/app.css"}
]
}
},
watch: {
styles: {
files: "./library/less/*",
tasks: ["less"],
options: {
nospawn: true,
},
},
},
});
// Event handling
grunt.event.on('watch', function(action, filepath){
// Update the config to only build the changed less file.
grunt.config(['less', 'development', 'files'], [
{src: filepath, dest: './library/css/' + path.basename(filepath, '.less') + '.css'}
]);
});
// Load the plugins
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
// Tasks
grunt.registerTask('default', ['watch']);
};
https://github.com/tschaub/grunt-newer looks like exactly for similar tasks:
Configure Grunt tasks to run with newer files only.
Synopsis: The newer task will configure another task to run with src files that are a) newer than the dest files or b) newer than the last successful run (if there are no dest files). See below for examples and more detail.
You can prepend easily to any task. In your case:
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('default', 'newer:coffee');
So new to Grunt 0.4 is more named tasks
Let us give you an example!
watch: {
package1: {
files: [
'./modules/package1/**/*.coffee'
],
tasks: ['coffee:package3']
},
package2: {
files: [
'./test_packages/package2/**/*.coffee'
],
tasks: ['coffee:package3']
},
package3: {
files: [
'./test_packages/package3/**/*.coffee'
],
tasks: ['coffee:package3']
},
}
To run all those watch tasks, simply do grunt.registerTask('default', ['myInitialBuild', 'watch']);
Where myInitialBuild
is whatever initial build (all of the files) then follow it up with a watch on each package. In reality you could do this for every file but that sounds sucky.