tschaub / gulp-newer

Pass through newer source files only
https://npmjs.org/package/gulp-newer
226 stars 24 forks source link

Doubt on the approach #4

Closed tomasdev closed 9 years ago

tomasdev commented 10 years ago

Hi @tschaub I found asking myself why is gulp-newer and gulp-changed having the same approach, with a dependency on the destination directory?

That drops the support for pipes that use gulp-rename for example, and I bet the modified source files are the ones that matter the most.

If source wasn't modified and the task is executed, destination doesn't really matter, does it? Am I missing something?

tschaub commented 10 years ago

The way these plugins determine if a source file has been modified is to check its mtime against the mtime of a corresponding destination file.

An alternative would be to cache the last previous run time of the task, and compare the source file's mtime to that. The advantage of this is that it works for tasks that don't produce destination files (e.g. lint). The disadvantage is that it requires extra storage for the cached run times (I think this is a minor disadvantage). In the grunt-newer task, both techniques are used - the last successful run time of a task is used if a task doesn't generate dest files.

I have plans to add support for last successful runtime comparison to gulp-newer. But I haven't made time to add this yet.

Can you provide an example Gulp task where the current strategy doesn't work (or an alternative strategy would be better)? I'm not sure I fully understand where you're coming from.

tomasdev commented 10 years ago

Yep. gulp-cache did the trick for me.

The strategy of checking dest files doesn't work when your destination folder will contain files renamed.

Example:

root
|-- src
   |-- modules
      |-- A
         |-- js
         |-- sass
            |-- a.scss
      |-- B
         |-- sass
            |-- b.scss
|-- dist
   |-- modules
      |-- A
         |-- css
            |-- b.css
      |-- B
         |-- css
            |-- b.css

The rename happens on transforming the sass to css in a "particular" folder, where the glob was /modules/**/sass/*.scss - I hope it's understandable.

Should the dist parameter passed be /modules/**/css/*.css?

Thanks!

pgilad commented 10 years ago

I think gulp-newer should be developed in thought of becoming a filter-plugin to either gulp-if or gulp-filter (which I prefer).

gulp-filter actually lets you run a function that gets the vinyl-file and thus you just need to return true/false.

This obviously poses a problem on async filtering but I'm it's something that can be improved/changed in gulp-filter.

Either way the filters should include gulp-newer but also:

  1. Hash comparison (gulp-different)
  2. Size comparison (gulp-size-diff)
  3. Name diff (gulp-name-diff)

Note these are just gulp filter I made up now, but there are use cases for them, most predominately - avoiding cleaning the build/ dir everytime before a dir, and rather - just update the newer/hash-different/size-different/name-different files.

Not sure this is directly related to the discussion but just my 2 cents.

tschaub commented 10 years ago

In some cases you also need to buffer all files, waiting to see if any one of them is newer, and then pass along all (for any concat style tasks).

And async filtering is definitely required.

pgilad commented 10 years ago

Hi @tschaub Just a note - I don't see any difference in the technical approach from a filter-plugin that needs to see if any of the files is (X) - to that of gulp-concat for instance.

I would also use through2 as it's much simpler and allows for better error handling.

Anyway my thoughts are on making a gulp-diff which aggregates this plugin, but adds: hash-diff, size-diff and name-diff.

But make it as simple as possible.

possible API:

passIfAny: {Boolean} - pass all files if any passes the conditions. default false.
diffMethod: {Array|String} - string of diff method, or array of diff methods for every file.
KevinBatdorf commented 9 years ago

I'm trying to accomplish something similar to the OP. My file structure looks like this, as an example:

public/
↳css/
  ↳styles.css
  ↳admin.css
  ↳min/
    ↳styles.min.css
    ↳mstyles.min.css.map
↳src/
  ↳scss/
    ↳_header.scss
    ↳_footer.scss
    ↳admin.scss
    ↳styles.scss

So I use gulp-sass to handle the scss files, and then use gulp-newer to check if the corresponding file is newer. However, it always comes back as not newer, and the file's aren't changed.

gulp.task('styles', function() {
    return gulp.src('src/scss/*.scss')
        .pipe(plumber())
        .pipe(sourcemaps.init({loadMaps: true}))
            .pipe(sass())
            .pipe(filelog())
            .pipe(newer('css'))
            .pipe(gulp.dest('css'))
            .pipe(prefix("last 1 version", "> 1%", "ie 8"))
            .pipe(minify())
            .pipe(rename({suffix: '.min'}))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('css/min'))
        .pipe(browserSync.reload({stream:true, once:true}))
        .pipe(notify({message: "Gulp styles task completed"}));
});

Maybe you see something I'm missing? I appreciate your time and the plugin works how I want when I have single files, like JS. Thanks

piotrd commented 9 years ago

@KevinBatdorf I'm having the same issues with my project. Maybe it's worth opening a separate task for this?

KevinBatdorf commented 9 years ago

This seems like so long ago that i don't even remember this code. but I checked back to what I ended up with and here's what I have. I'm assuming I got it to work...

gulp.task('styles', function () {
  return gulp.src(paths.sass)
    .pipe(plumber(function (error) {
      gutil.beep();
      gutil.log(gutil.colors.red(error.message));
      this.emit('end');
    }))
    .pipe(newer(themeDir + '/css/style.min.css'))
    .pipe(sourcemaps.init())
      .pipe(sass({errLogToConsole: true}))
      .pipe(prefix())
      .pipe(minify())
      .pipe(rename(function (path) {
        path.extname = ".min.css";
      }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest(themeDir + '/css'))
    .pipe(reload({stream:true, once:true}));
});