How can I use grunt-regarde with grunt-contrib-coffee to only compile changed .coffee files?

前端 未结 3 820
长发绾君心
长发绾君心 2020-12-29 10:57

My project has over 300 CoffeeScript files, so it takes several seconds to recompile everything. I\'d like to only recompile the changed CoffeeScript files.

Here\'s

相关标签:
3条回答
  • 2020-12-29 11:52

    I've had the same issue. I solved it using the regarde:file event.

    First I listen for changed files by using the regarde:file event. This will feed the configuration for two tasks: clean:coffee if files in the source location has been deleted and coffee:refresh if files have been changed/added.

    Then the regarde task will trigger its tasks, which will launch refresh:coffee (not to be mistaken from coffee:refresh). This task will check if there is configuration added for clean:coffee and/or for coffee:refresh and run these tasks if needed (via function grunt.task.run). If will also reset the flag, which will cause the next received regarde:file event to cleanup the configuration again.

    In depth explanation:

    First of all, regarde config:

     // watch for changed coffeescript files
     coffee: {
        files: 'path/to/coffee/**/*.coffee',
        tasks: ['refresh:coffee', 'livereload']
     },
    

    Then I listen for the regarde:file event, where I update the clean:coffee and coffee:refresh file lists in their config.

    Feed the configuration based on the regarde:file event:

    grunt.event.on('regarde:file', function (status, target, filepath) {
       if (resetFlag) {
          // clean file list from previous cycle, so clean clean:coffee and coffee:refresh
          // file lists
          ...
    
          resetFlag = false;
       } 
       if (status === 'deleted') {
            if (filepath) {
                // calculate filepath's destination and  
                // add it to clean:coffee filelist
            }
        } else {
            if (!grunt.file.isDir(filepath)) {
                // add filepath to coffee:refresh filelist
            }
        }
    }
    

    It is easy to update configuration via grunt.config() function. Below the code snippets to feed coffee:refresh and clean:coffee.

    Adding config to coffee:refresh:

    var config = grunt.config('coffee') || {};
    var value = config.refresh || {};
    value.files = value.files || [];
    ...
    var cwd = path.dirname(filepath),
        src = path.basename(filepath),
        dest = cwd.replace('path/to/source', 'path/to/dest');
        value.files.push({
           expand:true,
           src:src,
           dest:dest,
           cwd:cwd,
           ext:'.js'
        });
    grunt.config('coffee', config);
    

    Adding config to clean:coffee:

        var cwd = path.dirname(filepath),
            src = path.basename(filepath),
            dest = cwd.replace('path/to/source', 'path/to/dest');
            value.src.push(path.join(dest, src.replace('coffee', 'js')));
        // clean only what has been removed
            config = grunt.config('clean') || {};
    
        config.coffee = value;
    
        grunt.config('clean', config);
    

    Task refresh:coffee gets triggered:

        grunt.registerMultiTask('refresh', 'refreshing the changed file(s)', function () {
            this.requires('regarde');
    
            var tasks = [];
            var clean = grunt.config('clean');
    
            // check if there is clean:refresh config available
            if (clean && clean[this.target]) {
                tasks.push('clean:' + this.target);
            }
            var config = grunt.config(this.target);
    
            // check if there is coffee:refresh config available
            if (config && config.refresh) {
                tasks.push(this.target + ':refresh');
            }
            // run the tasks
            grunt.task.run(tasks);
    
            // set the resetFlag back to true
            resetFlag = true;
        });
    
    0 讨论(0)
  • 2020-12-29 11:54

    I had this issue myself and I was able to come up with a solution for it inspired by the comments on this issue: https://github.com/gruntjs/grunt-contrib-watch/issues/14

    It is actually for the grunt-contrib-watch plugin, but it should also work for grunt-regarde, as it has similar events.

    The idea is to bind a callback the watch event, in which you add a new task to the grunt configuration with the changed file's path, then run it.

    From my Gruntfile.coffee:

    coffee:
        app:
            expand: true
            cwd: 'app/'
            src: ['*.coffee',"**/*.coffee"]
            dest: './public/temp'
            ext: '.js'
    watch: 
        coffee:
            files: ['app/**/*.coffee']
            tasks: ['livereload']
            options:
                nospawn: true
    
    grunt.event.on 'watch', (action, filepath) ->       
        cwd = 'app/'
        filepath = filepath.replace(cwd,'')
        grunt.config.set('coffee',
            changed:
                expand: true
                cwd: cwd
                src: filepath
                dest: './public/temp'
                ext: '.js'
        )
        grunt.task.run('coffee:changed')
    

    The nospawn is important for the watch task, so it runs the new task before the livereload task. I am pretty sure regarde does not spawn child processes by default.

    0 讨论(0)
  • 2020-12-29 11:58

    grunt.regarde.changed is an array correct?

    Should src: ['<%= grunt.regarde.changed %>']

    be src: '<%= grunt.regarde.changed %>'

    I looked through grunt-contrib-coffee's source for a second to see if it could be not correctly handling whatever you're giving it. Looked kind of likely that the stringified array you're giving it, doesn't get caught and dealt with.

    I think what you're passing accidentally may be: src: [ '[path1, path2, path3, etc]' ]

    If I'm way off base, leave a comment and I'll delete this answer.

    0 讨论(0)
提交回复
热议问题