我遇到了类似的要求,我最终得到的解决方案大致如下。我们假设项目结构是:
Gruntfile.js
package.json
src/
config.js
data.js
tasks/
customtask.js
这里,src 目录包含将由watch 监控的数据,而自定义任务的定义存储在tasks/customtask.js 中。出于本示例的目的,此任务将仅打印更改文件的文件名:
var fs = require('fs');
var path = require('path');
module.exports = function(grunt) {
grunt.registerMultiTask('customtask', function() {
var done = this.async();
if(!this.files){ done(); return; }
this.files[0].src.forEach(file_name => {
console.log(file_name);
});
done();
});
};
现在,Gruntfile.js 看起来像:
module.exports = function(grunt) {
const files = ['src/config.js', 'src/data.js'];
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
customtask: {
release: {
src: files
}
},
watch: {
data: {
files: files,
tasks: ['customtask:release']
},
options: {
spawn: false
}
}
});
grunt.loadTasks('tasks');
grunt.loadNpmTasks('grunt-contrib-watch');
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
grunt.config('customtask.release.src', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
grunt.registerTask('build', ['watch:data']);
};
这里,它指定:
- 感兴趣的文件是
['src/config.js', 'src/data.js']
- 我们的
customtask 原则上对这些文件进行操作(以防被直接调用)
-
watch 应该观察这些文件并在发生变化时启动 customtask:release
-
grunt.loadTasks('tasks') 从目录tasks 加载所有“任务定义”,即这里只有customtask
-
grunt.registerTask('build', ['watch:data']) 为 watch:data 定义了一个“快捷方式”
最后,为了只为更改的文件调用customtask,此示例使用“按需编译文件”部分中documentation 中采用的策略。简而言之,它将所有更改的文件组装在一个对象中,然后使用其键来即时修改customtask 的src 属性。
运行grunt build 然后启动“监视”。如果在另一个终端窗口中运行,例如touch src/*.js,则输出为:
Running "watch:data" (watch) task
Waiting...
>> File "src/config.js" changed.
>> File "src/data.js" changed.
Running "customtask:release" (customtask) task
src/config.js
src/data.js
最后两行来自customtask...