-->

Grunt - how to watch and synchronize files' de

2019-04-09 10:23发布

问题:

I am a new user of Grunt. Currently I have a folder static_src/img that contains image source files (.psd) and image files (.png, .jpg, etc.). This folder is not public. Instead, I want to sync the change of only image files to another public folder static/img.

The problem is - it works well when I add/change a image file in static_src/img, but I don't know how to sync the change when I delete a file. Grunt-contrib-watch can detect the deletion in static_src/img, but I don't know how to delete the file in static/img. I tried grunt-contrib-clean, but it seems not work for me, maybe I used it not properly.

My Gruntfile.js is:

module.exports = function(grunt){
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      dev: {
        files: [
          {expand: true, cwd: 'static_src/img/', src:['**/*.{png,jpg,gif}'], dest: 'static/img/'}
        ]
      }
    },
    clean: {
      dev: {
        src: ['static_src/img/**/*.png']
      }
    },
    watch: {
      copy: {
        files: ['static_src/img/**/*.{png,jpg,gif}'],
        tasks: ['copy'],
        options: {
          event: ['added', 'changed'],
        }
      },
      remove: {
        files: ['static_src/img/**/*.{png,jpg,gif}'],
        tasks: ['clean'],
        options: {
          event: ['deleted']
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-watch');
};

So how to delete a specific file in a grunt-contrib-watch task? Thank you for help!

回答1:

For deleted event, you can delete all files in static/img and copy remaining files in static_src/img to static/img.

module.exports = function(grunt){
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      dev: {
        files: [
          {expand: true, cwd: 'static_src/img/', src:['**/*.{png,jpg,gif}'], dest: 'static/img/'}
        ]
      }
    },
    clean: {
      dev: {
        src: ['static/img/**/*.{png,jpg,gif}']    // Changed this from static_src to static
      }
    },
    watch: {
      copy: {
        files: ['static_src/img/**/*.{png,jpg,gif}'],
        tasks: ['copy'],
        options: {
          event: ['added', 'changed'],
        }
      },
      remove: {
        files: ['static_src/img/**/*.{png,jpg,gif}'],
        tasks: ['clean', 'copy'],    // Added copy task after clean
        options: {
          event: ['deleted']
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-watch');
};

I guess this might be different from what you expected to delete a specific file, but works as expected.



回答2:

Grunt has a file API that you can leverage with events, so you can write a delete function that runs when a given watched file is deleted:

grunt.event.on('watch', function(action, filepath, target) {
  if (action === 'deleted') {
    grunt.file.delete(fileToDelete);
  } 
});

The filepath is passed in, so you can do something like a regex to get the file name and prepend it with the appropriate path (if needed).



回答3:

I strongly recommend using nodejs' watch wrapper, which seems more stable (in Dec 2013) and versatile than native fs.watch / fs.watchFile.

https://github.com/paulmillr/chokidar

Tasty thing is also its API:

  .on('add'
  .on('addDir'
  .on('change'
  .on('unlink'
  .on('unlinkDir'
  .on('error'

My rough benchmarks don't show performance problems when using this module.

Of course it's not a finished answer to your question, but a tip. Hope it helps.



回答4:

I made a task for this:

https://github.com/taylorcode/grunt-delete-sync

Hope this helps. Beware of destructive nature.



回答5:

Try out my duplicate, which may fit your needs.

It will delete the dest file if the source is deleted, and also it will delete empty folders after delete its contents.



回答6:

Using grunt-rsync instead of the copy task, you can synchronize the deletion of files by using the delete option.



回答7:

This is an old question, but for anyone landing here in 2016 or later, there is now a grunt-sync task which handles complete synchronization, including deleting files: https://github.com/tomusdrw/grunt-sync