How to run a task ONLY on modified file with Gulp

2019-01-22 16:56发布

问题:

I have the current gulp task which I use in a gulpfile. Path are from a config.json and everything works perfectly:

//Some more code and vars...

gulp.task('watch', function() {
    gulp.watch([config.path.devfolder+"/**/*.png", config.path.devfolder+"/**/*.jpg", config.path.devfolder+"/**/*.gif", config.path.devfolder+"/**/*.jpeg"], ['imagemin-cfg']);
})

//Some more code ...

gulp.task('imagemin-cfg', function () {
    return gulp.src([config.path.devfolder+"/**/*.png", config.path.devfolder+"/**/*.jpg", config.path.devfolder+"/**/*.gif", config.path.devfolder+"/**/*.jpeg"], {read: false})
        .pipe(imagemin({
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngcrush()]
        }))
        .pipe(gulp.dest(buildType))
        .pipe(connect.reload());
});

But I still have an issue, the number of images in my project is huge and this task takes ages. I'm looking for a way to run my task ONLY on modified files. If I had an image or modify it, imagemin() will only run on this image, and not on all.

Once again everything is working perfectly fine, but the run time is really long.

Thanks.

回答1:

"gulp-changed" is not a best solution for doing this, because it watch only modified filed in "buildType" folder.

Try gulp-cached instead.



回答2:

Another option is to used the gulp.watch on("change") option.

gulp
  .watch([config.path.devfolder+"/**/*.png", config.path.devfolder+"/**/*.jpg", config.path.devfolder+"/**/*.gif", config.path.devfolder+"/**/*.jpeg"])
  .on("change", function(file) {
      gulp
        .src(file.path)
        .pipe(imagemin({
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngcrush()]
        }))
        .pipe(gulp.dest(buildType))
        .pipe(connect.reload());
  });


回答3:

With gulp.watch, you can target just the changed file like this.

gulp.watch(["src/**/*"], function (obj) {
 return gulp.src(obj.path, {"base": "src/"})
 .pipe(gulp.dest("dest"));
});


回答4:

May I suggest gulp-newy in which you can manipulate the path and filename in your own function. Then, just use the function as the callback to the newy(). This gives you complete control of the files you would like to compare.

This will allow 1:1 or many to 1 compares.

newy(function(projectDir, srcFile, absSrcFile) {
  // do whatever you want to here. 
  // construct your absolute path, change filename suffix, etc. 
  // then return /foo/bar/filename.suffix as the file to compare against
}



回答5:

Yeah, gulp-changed does exactly that:

var changed = require('gulp-changed');

gulp.task('imagemin-cfg', function () {
return gulp.src([config.path.devfolder+"/**/*.png", config.path.devfolder+"/**/*.jpg", config.path.devfolder+"/**/*.gif", config.path.devfolder+"/**/*.jpeg"], {read: false})
    .pipe(changed(buildType))
    .pipe(imagemin({
        progressive: true,
        svgoPlugins: [{removeViewBox: false}],
        use: [pngcrush()]
    }))
    .pipe(gulp.dest(buildType))
    .pipe(connect.reload());
});


回答6:

In the task or callback, you'll have an event parameter, which has a type property, which will tell you if the file was added, deleted or changed. Best bet is to make use of that in a conditional on your task.

gulp.watch('path to watch', function(event){
  if(event.type === 'changed') { 
    gulp.start('your:task');
  }
};


回答7:

Here's a real-world example I use all the time to do this without the need for any additional packages. I use this to minify, rename and compile any .js file in the js directory. Compiled files are saved to a dist directory with .min appended before the extension.

// Compile JS
var compileJS = function( file ) {
    var currentDirectory = process.cwd() + '/';
    var modifiedFile = file.path.replace( currentDirectory, '' );

    gulp.src( modifiedFile )
        .pipe( uglify() )
        .pipe( rename( {
            suffix: ".min"
        } ) )
        .pipe( livereload() )
        .pipe( gulp.dest( 'dist' ) );
};

// Watch for changes
gulp.watch( 'js/*.js', [ 'js' ] ).on( "change", compileJS );

The above answers seemed partially incomplete and a little unclear to me, hopefully this is helpful for anyone else looking for a basic example.