3

I'm trying to rebuild my gulp file to be a bit more efficient, and I'm having some trouble getting my styles task to only compile if a file has changed.

I found this question, but the answer doesn't seem to be working for me.

Let's say I have my repo organized like so:

/dev
  /assets
    /styles
      all.css
/src
  /assets
    /styles
      all.scss
      _header.scss
gulpfile.js
package.json

I only want to overwrite all.css if a change has been made in either of my Sass files. So, if I where to save _header.scss but no changes had been made, and ran my styles task, it should realize that the code hasn't changed and not overwrite all.css.

I was looking at gulp-cached, per the question I linked to above, but that doesn't seem to be working for me. Here's the task at it's most basic:

var gulp = require("gulp"),
    cached = require("gulp-cached"),
    sass = require("gulp-sass");

gulp.task("styles", function() {
    return gulp.src(src + "/assets/styles/all.scss")
        .pipe(sass().on("error", sass.logError))
        .pipe(cached("sass_compile")) // should skip the dest if cache is the same
        .pipe(gulp.dest(dev + "/assets/styles"));
});

The cached pipe doesn't seem to be working in this instance. I run gulp styles and it still overwrites all.css, even if no changes have been made, even if I didn't even re-save the file.

The more complex task I'd eventually like to use is:

var gulp = require("gulp"),
    cached = require("gulp-cached"),
    sourcemaps = require("gulp-sourcemaps"),
    sass = require("gulp-sass"),
    autoprefixer = require("gulp-autoprefixer"),

    // set up environment paths
    src = "./src",
    dev = "./dev",
    dist = "./dist";

gulp.task("styles", function() {
    return gulp.src(src + "/assets/styles/all.scss")
        .pipe(sourcemaps.init())
        .pipe(sass().on("error", sass.logError))
        .pipe(autoprefixer("last 2 version", "ie 8", "ie 9"))
        .pipe(sourcemaps.write())
        .pipe(cached("sass_compile")) // should skip the dest if cache is the same
        .pipe(gulp.dest(dev + "/assets/styles"));
});

Would greatly appreciate some guidance on this. Thanks much.


EDIT 1: Note that all.scss in this demo only contains @import "_header";.


EDIT 2: Okay, I just figured out that gulp-cached seems to be working fine in a watch task. So revised question: How can I get this same type of functionality outside of the watch task?

Community
  • 1
  • 1
JacobTheDev
  • 17,318
  • 25
  • 95
  • 158

2 Answers2

1

gulp-newer solved this problem, it can check imported files. Pretty awesome! Here's my final styles task:

// styles task, compiles & prefixes SCSS
gulp.task("styles", function () {
    "use strict";

    // development CSS directory
    var cssDirectory = dev + "/assets/styles";

    // production CSS directory (if --dist is passed)
    if (argv.dist) {
        cssDirectory = dist + "/assets/styles";
    }

    // clean directory if --clean is passed
    if (argv.clean) {
        del(cssDirectory + "**/*");
    }

    // compile all SCSS in the root styles directory
    return gulp.src(src + "/assets/styles/*.scss")
        // check if source is newer than destination
        .pipe(newer(cssDirectory + "/all.css"))
        // initialize sourcemap
        .pipe(sourcemaps.init())
        // compile SCSS (compress if --dist is passed)
        .pipe(gulpif(argv.dist, sass({outputStyle: "compressed"}).on("error", sass.logError), sass().on("error", sass.logError)))
        // prefix CSS
        .pipe(autoprefixer("last 2 version", "ie 8", "ie 9"))
        // write the sourcemap (if --dist isn't passed)
        .pipe(gulpif(!argv.dist, sourcemaps.write()))
        // output to the compiled directory
        .pipe(gulp.dest(cssDirectory));
});
JacobTheDev
  • 17,318
  • 25
  • 95
  • 158
0

Try gulp-changed instead. I believe that works on the last modified date of the file, which sounds like what you want.

dvlsg
  • 5,378
  • 2
  • 29
  • 34
  • Think I took a look at this and was running in to issues, but I'll give it another shot and report back. Thanks for the suggestion. – JacobTheDev Jan 15 '16 at 22:00
  • I *think* you can wrangle it into what you need. You probably need to use `changed` much earlier in the pipeline, so you can compare the src `all.scss` last changed date with the dest `all.scss` last changed date. IIRC it does the comparison based on filenames, so if you're doing any additional renaming / concatenating or anything like that, it can become problematic. Personally, I always end up just using something like `gulp-cached` in a watch task, but I tend to prefer watch tasks anyways. – dvlsg Jan 15 '16 at 22:05
  • So from that description it sounds like `changed` doesn't see changes in imported files, is that right? I'll do some research this weekend. I suppose I could just rely on the watch task; I'd just prefer to be able to manually run my default task (which runs all tasks) in some circumstances. – JacobTheDev Jan 15 '16 at 22:39
  • I think its designed to be a 1 to 1 comparison between a single source file and a single destination file with the same name. The comparison method can be different, but the default should be the last modified date -- so if it sees that the source file has a more recent last modified date than the destination file, then it should allow the source file through the pipe. – dvlsg Jan 15 '16 at 22:43
  • `gulp-diff` seems to almost offer what I'm looking for, but I'm having trouble getting it to error if a diff wasn't detected. Posted an issue [here](https://github.com/creativelive/gulp-diff/issues/5) – JacobTheDev Jan 18 '16 at 15:18
  • Been super busy, haven't had time to look in to this any more till just now. I did a bit more research, and it sounds like [gulp-newer](https://github.com/tschaub/gulp-newer) might be what I'm looking for. Hoping to give it a shot tomorrow. – JacobTheDev Jan 21 '16 at 02:26
  • 1
    Yeah, that looks promising -- nice that they have the capability to compare multiple src files against a single dest file (in the case of minification), as well. – dvlsg Jan 21 '16 at 18:14
  • gulp-newer seems to have done it, posted my updated task as an answer. Thanks for the suggestions, you led me down the right path :) – JacobTheDev Jan 21 '16 at 21:49