使用grunt-contrib-watch进行两个目录的深度单向同步.代码有效,但grunt-contrib-watch重新启动时间太慢

Sea*_*son 14 javascript gruntjs grunt-contrib-watch

我有两个目录srccompiled.我想,以确保从单向的数据同步srccompiled步兵关注.作为中间步骤,我想编译*.less文件以及*.js使用ES6语法编写的文件子集.

我已经成功地编写了我需要的任务:

// 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\\', ''));
    }
  });
Run Code Online (Sandbox Code Playgroud)

这些任务会监视相应的文件.事件处理程序动态修改clean copybabel执行任务,以便它们对添加/更改/删除的文件起作用.

但是,我正在观看几千个文件,并且监视任务需要花费大量的时间进行初始化.在我的高端开发中,PC 初始化需要6秒以上.手表任务在每项任务后重新初始化的事实加剧了这个问题.

这意味着,如果我有两个文件,fileA并且fileB我修改fileA并保存,那么有一个6+秒的时间段,其中watch无法检测到修改fileB.这导致我的两个目录之间的去同步.

我发现这个关于我的问题的GitHub问题,但它仍然是开放的,没有答案:https://github.com/gruntjs/grunt-contrib-watch/issues/443

关于GitHub的讨论强调,问题可能只spawn: false在设置时才会发生,但是,根据Grunt Watch文档:

如果需要动态修改配置,则必须禁用spawn选项以使监视在相同的上下文中运行.

因此,我相信我需要继续使用spawn: false.

我必须假设这是Grunt任务的一个非常标准的程序.我错过了一些明显的东西吗?Watch任务不适用于此目的吗?其他选择?

Sea*_*son 4

好吧,我有一个可行的解决方案,但它并不漂亮

我最终使用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\\', ''));
  }
});
Run Code Online (Sandbox Code Playgroud)

现在,仅当“src”比“dest”新时才会复制 ES6 文件以及非 LESS/非 ES6 文件。

不幸的是,grunt-newer 并不真正支持从“src”删除时同步删除操作。因此,我继续使用以前的代码进行“删除”操作。这仍然存在相同的缺陷,即在发生删除后,监视任务将暂时失效。