你如何在Grunt.js中观看多个文件,但只在更改的文件上运行任务?

时间:2012-08-21 21:23:54

标签: javascript node.js gruntjs

在学习如何使用grunt时,我正在尝试制作一个简单的咖啡脚本观察器/编译器。问题是,如果我告诉watch任务看多个文件,并且一个更改,它将把所有文件传递给coffee命令。这意味着当您更改1个文件时,它将重新编译与src模式匹配的文件的所有。相反,我只想重新编译与src模式匹配的单个文件。

以下是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');
};

这是使用grunt-coffee,基本上是这样的:https://gist.github.com/2373159

当我运行grunt watch并在test/cases/controller/*.coffee中保存文件时,它会编译匹配文件的所有(将它们放在tmp/*中)。< / p>

您如何使用grunt 仅编译已更改的文件

7 个答案:

答案 0 :(得分:15)

即将发布的(当前正在开发中)v0.4.0a grunt具有grunt.file.watchFiles对象,该对象专为此目的而设计。 grunt-coffee插件可能已经添加了对此功能的支持,我不确定。

无论哪种方式,如果您有兴趣在项目中尝试开发版本的grunt,请查看When will I be able to use in-development feature 'X'?常见问题解答条目。

答案 1 :(得分:8)

我在编译较少的文件时得到了这个功能。您应该能够使用coffeescript插件轻松搞砸这个配置。感兴趣的部分是grunt.event.on('watch', ...)。在这个事件处理程序中,我正在更新less命令中的files属性,只包含已更改的文件。

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']);
};

答案 2 :(得分:4)

这些答案对我来说都不是很有效。如果有人有兴趣,这是我的解决方案(我知道我回答这个问题的时间有点迟了。)

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

答案 3 :(得分:3)

在此issue中,Kyle Robinson建议使用watch事件。将监视任务nospawn属性设置为true以使其正常工作非常重要。我修改了他的解决方案以选择性地运行任务:

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]);
    }
});

以下是完整的解决方案:https://gist.github.com/luissquall/5408257

答案 4 :(得分:3)

https://github.com/tschaub/grunt-newer看起来完全符合类似的任务:

  

将Grunt任务配置为仅使用较新的文件运行。

     

概要:较新的任务将配置另一个与src一起运行的任务   a)比dest文件更新的文件或b)比last文件更新的文件   成功运行(如果没有dest文件)。请参阅下面的示例   还有更多细节。

您可以轻松地添加到任何任务中。在你的情况下:

  grunt.loadNpmTasks('grunt-newer');
  grunt.registerTask('default', 'newer:coffee');

答案 5 :(得分:2)

Grunt 0.4的新功能是更多命名的任务

让我们举个例子!

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']
    },
}

要运行所有这些监视任务,只需执行     grunt.registerTask('default',['myInitialBuild','watch']);

其中myInitialBuild是初始构建(所有文件),然后在每个包上使用监视器跟进。实际上,您可以为每个文件执行此操作,但这听起来很糟糕。

答案 6 :(得分:2)

任务grunt-contrib-watch现在支持这一点。

https://npmjs.org/package/grunt-contrib-watch - &gt;寻找“根据需要编译文件”

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);
});

这可以防止任务在每次发生变化时编译所有文件。