How do you look at several files, but only run the task on the modified file, in Grunt.js?

While learning how to use grunt , I am trying to make a simple caffeine script watcher / compiler. The problem is that if I talk about the watch task to view several files, and one of them changes, it will transfer all the files to the coffee command. This means that when you change 1 file, it is going to recompile all files matching the src pattern. Instead, I only want to recompile a single modified file matching the src pattern.

Here is grunt.js :

 module.exports = function(grunt) { grunt.initConfig({ coffee: { app: { src: ['test/cases/controller/*.coffee'], dest: 'tmp', options: { bare: true, preserve_dirs: true } } }, watch: { files: ['<config:coffee.app.src>'], tasks: ['coffee:app'] } }); grunt.loadNpmTasks('grunt-coffee'); grunt.registerTask('default', 'coffee'); }; 

This is used by grunt-coffee , which is basically like this: https://gist.github.com/2373159 .

When I run grunt watch , and I save the file in test/cases/controller/*.coffee , it compiles all the relevant files (putting them in tmp/* ).

How do you compile the modified file with grunt instead?

+43
javascript gruntjs
Aug 21 '12 at 21:23
source share
7 answers

In the upcoming (and currently under development) v0.4.0a grunt there is a grunt.file.watchFiles object that has been specifically designed for this purpose. Perhaps the grunt-coffee plugin can add support for this feature, I'm not sure.

In any case, if you are interested in trying to implement the grunt version in your project, see When can I use the built-in "X" function? FAQ

+15
Aug 22 2018-12-12T00:
source share

I got this working while compiling my smaller files. You should be able to adapt a bit to this configuration for git by working with the coffeescript plugin. The part of interest is grunt.event.on('watch', ...) . In this event handler, I update the files property in the less command to only contain the modified 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']); }; 
+7
Jul 01 '13 at 0:56
source share

None of these answers worked very well for me. Here is my solution if anyone is interested (I know that I answer this question a bit late).

https://gist.github.com/ryansmith94/8569178

+4
Jan 22 '14 at 23:00
source share

In this issue, Kyle Robinson suggests using the watch event. It is very important to set the watch t nospawn to true for it to work. I changed its solution to selectively run 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

+3
Apr 17 '13 at 22:28
source share

https://github.com/tschaub/grunt-newer looks exactly for similar tasks:

Configure Grunt tasks to run only with newer files.

Summary: the new task will configure another task to run using src files that are a) newer than the dest files, or b) newer than the last successful launch (if there are no dest files). See the examples below and in more detail.

You can easily add any task. In your case:

  grunt.loadNpmTasks('grunt-newer'); grunt.registerTask('default', 'newer:coffee'); 
+3
Mar 22 '14 at 9:27
source share

So, new to Grunt 0.4 - more named tasks

Let's give 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 these tasks, simply do grunt.registerTask ('default', ['myInitialBuild', 'watch']);

Where myInitialBuild is some kind of initial build (all files), and then follow it with the clock on each package. In fact, you can do this for each file, but it sounds juicy.

+2
Jun 19 '13 at 13:33
source share

The grunt-contrib-watch task now supports this.

https://npmjs.org/package/grunt-contrib-watch → look for "Compile 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 tasks from compiling all the files every time something changes.

+2
Aug 12 '13 at 7:58
source share



All Articles