8

I have grunt setup to compile all of my coffee files into javascript and maintain all folder structures using dynamic_mappings which works great.

coffee: {
  dynamic_mappings: {
    files: [{
      expand: true,
      cwd: 'assets/scripts/src/',
      src: '**/*.coffee',
      dest: 'assets/scripts/dest/',
      ext: '.js'
    }]
  }
}

What I would like to do is then use watch to compile any changed coffee file and still maintain folder structure. This works using the above task with this watch task:

watch: {
  coffeescript: {
    files: 'assets/scripts/src/**/*.coffee',
    tasks: ['coffee:dynamic_mappings']
  }
}

The problem is that when one file changes it compiles the entire directory of coffee into Javascript again, it would be great if it would only compile the single coffee file that was changed into Javascript. Is this naturally possible in Grunt or is this a custom feature. The key here is it must maintain the folder structure otherwise it would be easy.

We have custom watch scripts at work and I'm trying to sell them on Grunt but will need this feature to do it.

James Billings
  • 448
  • 7
  • 16
  • Would something like this work for you: [Github link: Compiling Files As Needed](https://github.com/gruntjs/grunt-contrib-watch#compiling-files-as-needed)? There is a further, interesting discussion here: [Github link: Provide conditional support for file inclusion.](https://github.com/gruntjs/grunt/issues/694) – dc5 Sep 19 '13 at 17:36
  • Duplicate: http://stackoverflow.com/questions/16203741/using-grunt-is-it-possible-to-compile-and-output-a-single-changed-file-to-a-dif -- but no good answers on that one – jcollum Sep 20 '13 at 15:41
  • I ran into this issue a few months ago and decided it wasn't worth worrying about -- it only takes about 2s for grunt to compile all of my coffee files (about 40 of them). – jcollum Sep 20 '13 at 15:42
  • We probably have about 200, my problem is our current system only compiles the one that changed so I can't sell anyone on a system thats slower. – James Billings Sep 20 '13 at 15:50
  • May not be possible "naturally" as you put it, but you could create separate targets (both in the `coffee` and `watch` tasks) for each file - and with 200 files, you might want to do so dynamically, but that is quite a bit more difficult. – Jordan Kasper Sep 20 '13 at 18:24
  • possible duplicate of [Grunt: Watch multiple files, Compile only Changed](http://stackoverflow.com/questions/16788731/grunt-watch-multiple-files-compile-only-changed) – bummi Apr 29 '14 at 16:13

2 Answers2

9

You can use something like the following Gruntfile. Whenever a CoffeeScript file changes, it updates the configuration for coffee:dynamic_mappings to only use the modified file as the src.

This example is a slightly modified version of the example in the grunt-contrib-watch readme.

Hope it helps!

var path = require("path");
var srcDir = 'assets/scripts/src/';
var destDir = 'assets/scripts/dest/';

module.exports = function( grunt ) {
    grunt.initConfig( {
        coffee: {
            dynamic_mappings: {
                files: [{
                    expand: true,
                    cwd: srcDir,
                    src: '**/*.coffee',
                    dest: destDir,
                    ext: '.js'
                }]
            }
        },
        watch : {
            coffeescript : {
                files: 'assets/scripts/src/**/*.coffee',
                tasks: "coffee:dynamic_mappings",
                options: {
                    spawn: false, //important so that the task runs in the same context
                }
            }
        }
    } );

    grunt.event.on('watch', function(action, filepath, target) {
        var coffeeConfig = grunt.config( "coffee" );
        // Update the files.src to be the path to the modified file (relative to srcDir).
        coffeeConfig.dynamic_mappings.files[0].src = path.relative(srcDir, filepath);
        grunt.config("coffee", coffeeConfig);
    } );

    grunt.loadNpmTasks("grunt-contrib-coffee");
    grunt.loadNpmTasks("grunt-contrib-watch");

    grunt.registerTask("default", [ "coffee:dynamic_mappings", "watch:coffeescript"]);
};
go-oleg
  • 19,272
  • 3
  • 43
  • 44
3

found a solution from an answer to a similar question https://stackoverflow.com/a/19722900/1351350

short answer: try https://github.com/tschaub/grunt-newer

Community
  • 1
  • 1
codeboy
  • 436
  • 5
  • 9
  • Great! Finally I can compile only the changed less files and still have the css livereload working! – Narretz Jul 23 '14 at 10:13