如何根据文件变化修改grunt watch任务?

5
我正在编写一个node.js程序,它会监视一个包含大量scss项目(约300个)的目录。通过配置grunt-watch(无论是通过节点模块还是独立运行),每当scss文件发生更改时,都会使用compass编译,并将输出文件移动到另一个目录,例如:
./1234/style.scss 发生更改 >> grunt-watch 运行 grunt-compass >> /foo/bar/baz/1234/style.css 更新
文件所在的项目目录显然非常重要(如果grunt-compass将所有编译后的文件发送到同一个目录中,它们就会混杂在一起,无法使用,grunt自动化也就没有意义)。为了确保所有文件都被路由到正确的位置,每次更新css文件时,我都会动态更改grunt-compass设置。
示例gruntfile:
module.exports = function(grunt) {

grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    watch: {
      files: './*/*.scss',
      tasks: ['compass']
    },
    compass: {
      origin:{
        options: {
          //temportary settings to be changed later
          sassDir: './',
          cssDir: './bar',
          specify: './foo.scss'
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-compass');

  grunt.event.on('watch', function(action, filepath, target) {
    var path = require('path');
    grunt.log.writeln(target + ': ' + filepath + ' might have ' + action);
    var siteDirectory = path.dirname(filepath);

    //changes sass directory to that of the changed file
    var option = 'compass.origin.options.sassDir';
    var result = __dirname + '/' + siteDirectory;
    grunt.log.writeln(option + ' changed to ' + result);
    grunt.config(option, result);

    //customizes css output directory so that file goes to correct place
    option = 'compass.origin.options.cssDir';
    result = path.resolve(__dirname, '../', siteDirectory);
    grunt.log.writeln(option + ' changed to ' + result);
    grunt.config(option, result);

    //grunt.task.run(['compass']);

  });

};

然而,这并不起作用。如果在详细模式下运行“grunt watch”,则会看到grunt在单独的进程中运行grunt.event.on函数和watch任务。对gruntfile的第二次解析将所有我的event.on配置更改恢复为上面的默认值,从而导致compass无法运行。
如event.on注释中所示,我尝试添加grunt.task.run()以确保在与event.on函数相同的进程中运行compass,这将保留我的配置更改。但是该任务拒绝运行,可能是因为我做错了。
不幸的是,grunt.event.on变量未发送到定义的grunt-watch任务,否则我可以编写自定义函数来更改compass设置,然后在同一个进程中运行compass。
我已经尝试使用内置于compass中的watch函数实现此操作,但是compass每个项目只能存储一个静态输出路径,并且一次只能监视一个项目。
我目前通过添加一个以网站名称为参数的节点程序来解决了这个问题,使用fs重写grunfile.js,并通过exec函数运行'grunt watch'。然而,这种方法有其自身的缺点(我无法查看grunt.log数据),而且非常复杂,因此我想进行更改。
非常感谢您提供的任何见解。

这并不回答你的问题,但为什么会有一个针对compass的grunt-contrib-watch?Compass已经带有compass watch - pllee
你需要在你的监视任务配置中指定 options : { nospawn : true },以便让 watch 在相同的上下文中运行(请参阅文档中的此部分)。 - go-oleg
@go-oleg 谢谢!那个方法非常有效。我很惊讶在文档中没有看到它,因为它直接说明了 nospawn 可以解决像我这样的问题。 - anachronism
@pllee grunt-contrib-watch 并非专为 Compass 设计,而是旨在与其他没有监视功能的自动化任务一起使用(如果您想编写自己的自定义任务,则变得非常方便)。 在许多情况下,compass watch 可能非常完美,但我在使用它来适应这个特定实例时遇到了问题,因此我选择了 grunt-contrib-watch - anachronism
我想我本意是说grunt-contrib-compass,但是看起来你遇到的问题似乎不是compass watch可以解决的。 - pllee
1个回答

11

你需要在你的监视任务配置中指定

options: { nospawn: true }

以便监视运行在相同的上下文中:

watch: {
  files: './*/*.scss',
  tasks: ['compass'],
  options : { nospawn : true }
}

请查看文档的此部分,以获取更多有关此内容的信息。


感谢这个答案。我已经阅读了文档,但对“context”的含义以及它如何受 nospawn 选项影响仍不清楚。非常感谢! - jerome
3
为了给这个答案添加更新,截至2016年6月,选项现在为:spawn: false - BigHeadCreations

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接