44

在学习如何使用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/*)。

您如何只使用 grunt编译更改的文件?

4

7 回答 7

15

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

无论哪种方式,如果您有兴趣在您的项目中尝试开发中的 grunt 版本,请查看我何时可以使用开发中功能“X”?常见问题解答条目。

于 2012-08-22T12:33:45.170 回答
8

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']);
};
于 2013-07-01T00:56:07.943 回答
4

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

于 2014-01-22T23:00:50.650 回答
3

本期中,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

于 2013-04-17T22:28:09.550 回答
3

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

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

概要:较新的任务将配置另一个任务以使用 src 文件运行,这些文件 a) 比 dest 文件新或 b) 比上次成功运行(如果没有 dest 文件)新。有关示例和更多详细信息,请参见下文。

您可以轻松地为任何任务添加前缀。在你的情况下:

  grunt.loadNpmTasks('grunt-newer');
  grunt.registerTask('default', 'newer:coffee');
于 2014-03-22T09:27:07.660 回答
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初始构建(所有文件)在哪里,然后在每个包上监视它。实际上,您可以对每个文件都这样做,但这听起来很糟糕。

于 2013-06-19T13:33:54.713 回答
2

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

https://npmjs.org/package/grunt-contrib-watch -> 查找“按需编译文件”

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

这应该可以防止任务在每次发生更改时编译所有文件。

于 2013-08-12T07:58:58.163 回答