使用 grunt-contrib-watch 深度单向同步两个目录。代码有效,但 grunt-contrib-watch 重新初始化时间太慢
Deep, one-way synchronization of two directories using grunt-contrib-watch. Code works, but grunt-contrib-watch re-init time is too slow
我有两个目录 src
和 compiled
。我想确保从 src
到 compiled
与 Grunt Watch 的单向数据同步。作为中间步骤,我想编译 *.less
个文件以及用 ES6 语法编写的 *.js
个文件的子集。
我已经成功编写了满足我需要的任务:
// NOTE: Spawn must be disabled to keep watch running under same context in order to dynamically modify config file.
watch: {
// Compile LESS files to 'compiled' directory.
less: {
options: {
interrupt: true,
spawn: false,
cwd: 'src/less'
},
files: ['**/*.less'],
tasks: ['less']
},
// Copy all non-ES6/LESS files to 'compiled' directory. Include main files because they're not ES6. Exclude LESS because they're compiled.
copyUncompiled: {
options: {
event: ['added', 'changed'],
spawn: false,
cwd: 'src'
},
files: ['**/*', '!**/background/**', '!**/common/**', '!contentScript/youTubePlayer/**/*', '!**/foreground/**', '!**/test/**', '!**/less/**', '**/main.js'],
tasks: ['copy:compileSingle']
},
// Compile and copy ES6 files to 'compiled' directory. Exclude main files because they're not ES6.
copyCompiled: {
options: {
event: ['added', 'changed'],
spawn: false,
cwd: 'src/js'
},
files: ['background/**/*', 'common/**/*', 'contentScript/youTubePlayer/**/*', 'foreground/**/*', 'test/**/*', '!**/main.js'],
tasks: ['babel:compileSingle']
},
// Whenever a file is deleted from 'src' ensure it is also deleted from 'compiled'
remove: {
options: {
event: ['deleted'],
spawn: false,
cwd: 'src'
},
files: ['**/*'],
tasks: ['clean:compiledFile']
}
}
grunt.event.on('watch', function(action, filepath, target) {
// Determine which task config to modify based on the event action.
var taskTarget = '';
if (action === 'deleted') {
taskTarget = 'clean.compiledFile';
} else if (action === 'changed' || action === 'added') {
if (target === 'copyCompiled') {
taskTarget = 'babel.compileSingle';
} else if (target === 'copyUncompiled') {
taskTarget = 'copy.compileSingle';
}
}
if (taskTarget === '') {
console.error('Unable to determine taskTarget for: ', action, filepath, target);
} else {
// Drop src off of filepath to properly rely on 'cwd' task configuration.
grunt.config(taskTarget + '.src', filepath.replace('src\', ''));
}
});
这些任务监视相应的文件。事件处理程序动态修改 clean
copy
和 babel
任务,以便它们处理 added/changed/removed.
的文件
但是,我正在监视数千个文件,并且监视任务需要大量时间来初始化。在我的高端开发 PC 上 初始化需要 6 秒以上。监视任务 在每个任务 .
后重新初始化这一事实加剧了这个问题
这意味着,如果我有两个文件,fileA
和 fileB
,并且我修改了 fileA
并保存,那么手表将在超过 6 秒的时间内无法检测到修改至 fileB
。这导致我的两个目录之间不同步。
我发现了这个 GitHub 关于我的问题的问题,但它仍然未解决且未得到答复:https://github.com/gruntjs/grunt-contrib-watch/issues/443
关于 GitHub 的讨论强调,问题可能仅在设置 spawn: false
时出现,但是,根据 Grunt Watch documentation:
If you need to dynamically modify your config, the spawn option must be disabled to keep the watch running under the same context.
因此,我认为我需要继续使用 spawn: false
。
我不得不假设这是 Grunt 任务的一个非常标准的过程。我在这里遗漏了一些明显的东西吗? Watch 任务不适合这个目的吗?其他选项?
好的,所以我有一个可行的解决方案,但它不漂亮。
我最终使用 grunt-newer 来协助解决问题。不幸的是,它不能很好地与 grunt-contrib-copy 配合使用,因为复制文件不会更新其最后修改时间,因此 grunt-newer 将在 100% 的时间内执行。
因此,我分叉了 grunt-contrib-copy 并添加了一个选项以允许更新上次修改时间:https://github.com/MeoMix/grunt-contrib-copy
有了它,我现在可以写:
// NOTE: Spawn must be disabled to keep watch running under same context in order to dynamically modify config file.
watch: {
// Compile LESS files to 'compiled' directory.
less: {
options: {
interrupt: true,
cwd: 'src/less'
},
files: ['**/*.less'],
tasks: ['less']
},
// Copy all non-ES6/LESS files to 'compiled' directory. Include main files because they're not ES6. Exclude LESS because they're compiled.
copyUncompiled: {
options: {
event: ['added', 'changed'],
cwd: 'src'
},
files: ['**/*', '!**/background/**', '!**/common/**', '!contentScript/youTubePlayer/**/*', '!**/foreground/**', '!**/test/**', '!**/less/**', '**/main.js'],
tasks: ['newer:copy:compiled']
},
// Compile and copy ES6 files to 'compiled' directory. Exclude main files because they're not ES6.
copyCompiled: {
options: {
event: ['added', 'changed'],
cwd: 'src/js'
},
files: ['background/**/*', 'common/**/*', 'contentScript/youTubePlayer/**/*', 'foreground/**/*', 'test/**/*', '!**/main.js'],
tasks: ['newer:babel:compiled']
},
// Whenever a file is deleted from 'src' ensure it is also deleted from 'compiled'
remove: {
options: {
event: ['deleted'],
spawn: false,
cwd: 'src'
},
files: ['**/*'],
tasks: ['clean:compiledFile']
}
}
grunt.event.on('watch', function(action, filepath) {
if (action === 'deleted') {
// Drop src off of filepath to properly rely on 'cwd' task configuration.
grunt.config('clean.compiledFile.src', filepath.replace('src\', ''));
}
});
现在只有 'src' 比 'dest.'
更新时才会复制 ES6 文件以及 non-LESS/non-ES6 文件
不幸的是,当从 'src' 中删除时,grunt-newer 并不真正支持同步删除操作。所以,我继续使用我以前的代码进行 'delete' 操作。此 仍然存在相同的缺陷,即在发生删除后 watch 任务将暂时失效。
我有两个目录 src
和 compiled
。我想确保从 src
到 compiled
与 Grunt Watch 的单向数据同步。作为中间步骤,我想编译 *.less
个文件以及用 ES6 语法编写的 *.js
个文件的子集。
我已经成功编写了满足我需要的任务:
// NOTE: Spawn must be disabled to keep watch running under same context in order to dynamically modify config file.
watch: {
// Compile LESS files to 'compiled' directory.
less: {
options: {
interrupt: true,
spawn: false,
cwd: 'src/less'
},
files: ['**/*.less'],
tasks: ['less']
},
// Copy all non-ES6/LESS files to 'compiled' directory. Include main files because they're not ES6. Exclude LESS because they're compiled.
copyUncompiled: {
options: {
event: ['added', 'changed'],
spawn: false,
cwd: 'src'
},
files: ['**/*', '!**/background/**', '!**/common/**', '!contentScript/youTubePlayer/**/*', '!**/foreground/**', '!**/test/**', '!**/less/**', '**/main.js'],
tasks: ['copy:compileSingle']
},
// Compile and copy ES6 files to 'compiled' directory. Exclude main files because they're not ES6.
copyCompiled: {
options: {
event: ['added', 'changed'],
spawn: false,
cwd: 'src/js'
},
files: ['background/**/*', 'common/**/*', 'contentScript/youTubePlayer/**/*', 'foreground/**/*', 'test/**/*', '!**/main.js'],
tasks: ['babel:compileSingle']
},
// Whenever a file is deleted from 'src' ensure it is also deleted from 'compiled'
remove: {
options: {
event: ['deleted'],
spawn: false,
cwd: 'src'
},
files: ['**/*'],
tasks: ['clean:compiledFile']
}
}
grunt.event.on('watch', function(action, filepath, target) {
// Determine which task config to modify based on the event action.
var taskTarget = '';
if (action === 'deleted') {
taskTarget = 'clean.compiledFile';
} else if (action === 'changed' || action === 'added') {
if (target === 'copyCompiled') {
taskTarget = 'babel.compileSingle';
} else if (target === 'copyUncompiled') {
taskTarget = 'copy.compileSingle';
}
}
if (taskTarget === '') {
console.error('Unable to determine taskTarget for: ', action, filepath, target);
} else {
// Drop src off of filepath to properly rely on 'cwd' task configuration.
grunt.config(taskTarget + '.src', filepath.replace('src\', ''));
}
});
这些任务监视相应的文件。事件处理程序动态修改 clean
copy
和 babel
任务,以便它们处理 added/changed/removed.
但是,我正在监视数千个文件,并且监视任务需要大量时间来初始化。在我的高端开发 PC 上 初始化需要 6 秒以上。监视任务 在每个任务 .
后重新初始化这一事实加剧了这个问题这意味着,如果我有两个文件,fileA
和 fileB
,并且我修改了 fileA
并保存,那么手表将在超过 6 秒的时间内无法检测到修改至 fileB
。这导致我的两个目录之间不同步。
我发现了这个 GitHub 关于我的问题的问题,但它仍然未解决且未得到答复:https://github.com/gruntjs/grunt-contrib-watch/issues/443
关于 GitHub 的讨论强调,问题可能仅在设置 spawn: false
时出现,但是,根据 Grunt Watch documentation:
If you need to dynamically modify your config, the spawn option must be disabled to keep the watch running under the same context.
因此,我认为我需要继续使用 spawn: false
。
我不得不假设这是 Grunt 任务的一个非常标准的过程。我在这里遗漏了一些明显的东西吗? Watch 任务不适合这个目的吗?其他选项?
好的,所以我有一个可行的解决方案,但它不漂亮。
我最终使用 grunt-newer 来协助解决问题。不幸的是,它不能很好地与 grunt-contrib-copy 配合使用,因为复制文件不会更新其最后修改时间,因此 grunt-newer 将在 100% 的时间内执行。
因此,我分叉了 grunt-contrib-copy 并添加了一个选项以允许更新上次修改时间:https://github.com/MeoMix/grunt-contrib-copy
有了它,我现在可以写:
// NOTE: Spawn must be disabled to keep watch running under same context in order to dynamically modify config file.
watch: {
// Compile LESS files to 'compiled' directory.
less: {
options: {
interrupt: true,
cwd: 'src/less'
},
files: ['**/*.less'],
tasks: ['less']
},
// Copy all non-ES6/LESS files to 'compiled' directory. Include main files because they're not ES6. Exclude LESS because they're compiled.
copyUncompiled: {
options: {
event: ['added', 'changed'],
cwd: 'src'
},
files: ['**/*', '!**/background/**', '!**/common/**', '!contentScript/youTubePlayer/**/*', '!**/foreground/**', '!**/test/**', '!**/less/**', '**/main.js'],
tasks: ['newer:copy:compiled']
},
// Compile and copy ES6 files to 'compiled' directory. Exclude main files because they're not ES6.
copyCompiled: {
options: {
event: ['added', 'changed'],
cwd: 'src/js'
},
files: ['background/**/*', 'common/**/*', 'contentScript/youTubePlayer/**/*', 'foreground/**/*', 'test/**/*', '!**/main.js'],
tasks: ['newer:babel:compiled']
},
// Whenever a file is deleted from 'src' ensure it is also deleted from 'compiled'
remove: {
options: {
event: ['deleted'],
spawn: false,
cwd: 'src'
},
files: ['**/*'],
tasks: ['clean:compiledFile']
}
}
grunt.event.on('watch', function(action, filepath) {
if (action === 'deleted') {
// Drop src off of filepath to properly rely on 'cwd' task configuration.
grunt.config('clean.compiledFile.src', filepath.replace('src\', ''));
}
});
现在只有 'src' 比 'dest.'
更新时才会复制 ES6 文件以及 non-LESS/non-ES6 文件不幸的是,当从 'src' 中删除时,grunt-newer 并不真正支持同步删除操作。所以,我继续使用我以前的代码进行 'delete' 操作。此 仍然存在相同的缺陷,即在发生删除后 watch 任务将暂时失效。