gulp-cached icon indicating copy to clipboard operation
gulp-cached copied to clipboard

Need an option to init the cache

Open thatkookooguy opened this issue 8 years ago • 9 comments

Currently, when I run my gulp watch task, everything is linted on the first save. The second time around, only the file I changed gets linted.

My question: Is there a way to enable some sort of init value? I want to cache all my javascript files the first time around if the cache is empty, but NOT lint at all. after that, start my piping and only the changed file will be linted

thatkookooguy avatar Dec 29 '15 15:12 thatkookooguy

@Thatkookooguy You can access the cache with cache.caches[cacheName] - if this allows you to solve the problem I can look into adding an option for this, lmk 🌴

yocontra avatar Dec 31 '15 22:12 yocontra

@contra @Thatkookooguy I think i have a similar problem. Imagine you have multiple css tasks that work from the same source (scss-compiler, scss-linter). Because of this you want to cache the contents under the same namespace fe: cache('scss-files'). In this scenario the very first task will run and all subsequent tasks will do nothing because the first task updated the cache.

Example (with optional pre task):

gulp.task('sass-lint', () => {
  return gulp.src(paths.src)
    .pipe(gulpIf(config.isDev, cache(config.css.cacheName)))
    .pipe(sassLint())
    .pipe(sassLint.format())
    .pipe(sassLint.failOnError());
});

const preTasks = (!config.sassLint.ideSupport && config.isDev) ? ['sass-lint'] : [];

gulp.task('css', preTasks, () => {
  return gulp.src(paths.src)
    .pipe(gulpIf(config.isDev, cache(config.css.cacheName)))
    .pipe(gulpIf(config.isDev, progeny()))
    ...
});

Solution: save the previous state of the cache somewhere and only update it at the very last of same cache namespaced task? How would you do this?

aegyed91 avatar Jan 08 '16 12:01 aegyed91

+1

Here's a workaround that I implemented in my gulpfile.js. This example allows creating a watch task that will only lint JavaScript files that have changed:

var gulp = require('gulp');

var gulpif = require('gulp-if');

var gulpCached = require('gulp-cached');

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

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

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

var through2 = require('through2');

(function () {
    'use strict';

    const linting = 'linting';

    var buildConfig = {
        flags: {
            watch: false,
            build: false
        },
        src: {
            scripts: ['./app/**/*.js', './src/**/*.js']
        }
    };

    var preCacheGulpCached = function (src, cache, cacheId, cb) {
        /* Pre-build a cache for gulp-cached plugin */

        var cacheEntry = cache.caches[cacheId] = cache.caches[cacheId] || {},
            cacheFile,
            stream;

        stream = gulp.src(src).pipe(through2.obj(function (file, encoding, callback) {
            var contents = file.checksum;

            if (!contents) {
                if (file.isStream()) {
                    this.push(file);

                    callback();
                }
                if (file.isBuffer()) {
                    contents = file.contents.toString('utf8');
                }
            }

            cacheFile = cacheEntry[file.path];

            if (typeof cacheFile !== 'undefined' && cacheFile === contents) {
                callback();
            }

            cacheEntry[file.path] = contents;

            this.push(file);

            callback();
        }, cb));

        return stream;
    };

    gulp.task('eslint', function () {
        return gulp.src(buildConfig.src.scripts)
            .pipe(eslint('.eslintrc'))
            .pipe(eslint.format())
            .pipe(eslint.failAfterError());
    });

    gulp.task('jscs', function () {
        return gulp.src(buildConfig.src.scripts)
            .pipe(jscs({ configPath: '.jscsrc' }))
            .pipe(jscs.reporter())
            .pipe(jscs.reporter('fail'));
    });

    gulp.task('lint', function () {
        return gulp.src(buildConfig.src.scripts)
            .pipe(gulpif(buildConfig.flags.watch, gulpCached(linting)))
            .pipe(eslint('.eslintrc'))
            .pipe(eslint.format())
            .pipe(jscs({ configPath: '.jscsrc' }))
            .pipe(jscs.reporter())
            .pipe(gulpif(buildConfig.flags.build, jscs.reporter('failImmediately')))
            .pipe(gulpif(buildConfig.flags.build, eslint.failAfterError()));
            //.on('error', process.exit.bind(process, 1)); alternatively, this could be used in place of eslint.failAfterError.
    });

    gulp.task('watch', function () {
        buildConfig.flags.watch = true;

        preCacheGulpCached(buildConfig.src.scripts, gulpCached, linting, function () {
            console.log('gulp-cached pre-cache complete');
        });

        gulp.watch(buildConfig.src.scripts, ['lint']);
    });

})();

cookch10 avatar Jan 14 '16 19:01 cookch10

I'm running into the same problem where I need to pre-cache before the watch triggers linting.

lewismoten avatar May 23 '16 18:05 lewismoten

@cookch10 tried your solution and for some reason I don't even see the console.log for the pre-cach being complete.

did something change? thanks for the script btw! it at least gave me a starting point :-)

thatkookooguy avatar Aug 31 '16 12:08 thatkookooguy

fixed it by making the following change:

var preCacheGulpCached = function (src, cache, cacheId, cb) {
  /* Pre-build a cache for gulp-cached plugin */

  var cacheEntry = cache.caches[cacheId] = cache.caches[cacheId] || {},
    cacheFile,
    stream;

  stream = gulp.src(src).pipe(through2.obj(function (file, encoding, callback) {
    var contents = file.checksum;

    if (!contents) {
      if (file.isStream()) {
        this.push(file);

        callback();
      }
      if (file.isBuffer()) {
        contents = file.contents.toString('utf8');
      }
    }

    cacheFile = cacheEntry[file.path];

    if (typeof cacheFile !== 'undefined' && cacheFile === contents) {
      callback();
    }

    cacheEntry[file.path] = contents;

    this.push(file);

    cb();
  }));

  return stream;
};

it looks like through2 now accepts only one variable

thatkookooguy avatar Aug 31 '16 12:08 thatkookooguy

So, since @cookch10 didn't work for me for some reason, I copied his idea and created a function to initialize the cache.

It's probably bad practice somewhere, but here we go:

var gulp = require('gulp'),
      cache = require('gulp-cached'),
      gulpif = require('gulp-if'),
      gcallback = require('gulp-callback');

var preCacheGulpCached = function (src, cacheId, cb) {
  /* Pre-build a cache for gulp-cached plugin */
  var callCallback = true; // fix callback executing more than once
  return gulp.src(src)
    .pipe(cache(cacheId))
    .pipe(gcallback(function() {
      if (callCallback && cb) {
        cb();
        callCallback = false;
      }
    }));
};

gulp.task('jscpd', function() {
  return gulp.src(FILES.LINT)
    .pipe(gulpif(buildConfig.flags.watch, cache('jscpd')))
    .pipe(jscpd({
      'min-lines': 10,
      verbose    : true
    }));
});

gulp.task('magicNumbers', function () {
  return gulp.src(FILES.JS_ALL)
    .pipe(gulpif(buildConfig.flags.watch, cache('magicNumbers')))
    .pipe(buddyjs({
      reporter: 'detailed'
    }));
});

gulp.task('watch', function() {
      buildConfig.flags.watch = true;

      preCacheGulpCached(FILES.JS_ALL, 'jscpd');
      preCacheGulpCached(FILES.JS_ALL, 'magicNumbers');
      if (argv.lint) {
        preCacheGulpCached(FILES.LINT, 'linting');
      }

      gulp.watch(argv.lint ? FILES.LINT : [], ['lint-js']);
      gulp.watch(FILES.JS_ALL, ['jscpd', 'magicNumbers']);
      gulp.watch(FILES.FRONTEND_SASS, ['styles']);
      gulp.watch(FILES.SERVER_JS).on('change', restart);
      gulp.watch(FILES.FRONTEND_ALL).on('change', function(file) {
        reloadBrowser('Frontend file changed.', file.path);
      });
    });

I use gulp-callback since I need something after the chache command. If I don't include something after the cache in preCacheGulpCached, The files aren't being cached.

~~I also tried to call the actual callback with gulp-callback but it printed out 3 times for each run so I removed it.~~ UPDATE: fixed the multiple callback execution

but it works!

thatkookooguy avatar Aug 31 '16 13:08 thatkookooguy

How would y'all want to see this functionality added to the project? Anyone want to propose some APIs?

yocontra avatar Aug 31 '16 15:08 yocontra

the way i managed files to be precached using @Thatkookooguy function:

gulp.task('watch-pages', function(){
  return preCache(templatePagesPath, 'pages', function(){
    gulp.watch(templatePagesPath, ['pages']);
  });
})

gulp.task('watch-styles', function(){
  return preCache(stylesheetsPath, 'styles', function(){
    gulp.watch(stylesheetsPath, ['styles']);
  });
})

gulp.task('watch', ['watch-pages','watch-styles']);

notice the return statement - without it caching doesn't work

gosteev avatar Oct 26 '16 00:10 gosteev