bingnz/gulp-less-changed

File is always passed through when it's dependencies have a higher modified time that the file

danielcardoso5 opened this issue · 11 comments

If I have a file with imports that doesn't get updated that often, by having a dependency on that file that is modified, the file will always pass through gulp-less-changed unless I change it's modified time. It should only pass the first time one of its dependencies changes.

A solution would probably be making a touch command on the main file so its modified time would be higher than its dependencies on the next run.

Hi Daniel,

I'm not really clear what the problem is here. The plugin actually records the last known update times of imports in the temp directory (npm config get tmp), so it might be that the files there aren't being created properly?
What should happen is that you specify the main .less file in the config, and its imports are tracked automatically by the plugin.
What does your config look like?

David

Hi David,

I believe the problem lies in the "checkImportsHaveChanged" function. If I understood the code correctly, it compares the modified time of each of the main file dependencies with the modified time of the main file. What happens is that since I changed the dependency and not the main file, this function will always return true because one of the dependencies will always have a higher modified time than the main file. Maybe I understood the code wrong or there's some problem on my end.

My config consists on a set of main files that mostly consist of imports, some of them are imports only. These files are compiled and passed through gulp-less-changed to check if one of their dependencies changed.

Hi Daniel,

The modified time of each file is compared against the modified time of the output file, not the main file. Once you've built everything once, the output file should obviously have a later timestamp than all of its input files until you touch one or more of them. The structure is cached in the temp directory because figuring out the dependency tree is expensive.

One possibility is that the plugin doesn't know the path of the output (.css or .min.css or whatever) file, in which case it will always assume you're running it for the first time. By default it assumes that if you have a file called 'xxx.less' that the output file will be 'xxx.css' but you can override this assumption using getOutputFileName in the options. There is no error or warning logged in this case; I thought about that, but this of course always happens when you build from a clean environment for the first time.
If it's not that, you could try clearing your temp directory and trying again.

Thanks,
David

Where can I find the temp directory?

I think it is detecting the correct output folder correctly. My less files are outputed to a build folder with the same name and the css extension.
The strange behaviour I'm able to reproduce is the following:

  • I clean the build folder

  • Run the task that processes the less files and it outputs all the files to the build folder

  • If I run it again not all the files processed before by gulp-less-changed are being passed through, this means the output folder is being detected correctly I believe

  • If I save one of the files that are still being passed through, even though the output file is more recent, on the next run it will be passed through again, but on the second run it won't

This is my task:

gulp.task("less-to-css", function () {
    return gulp.src(paths.less_to_compile)
        .pipe(lessChanged({
            getOutputFileName: function (file) {
                return ren(file, {
                    dirname: paths.build,
                    extname: ".css"
                });
            }
        }))
        .pipe(print(function (filepath) {
            return "Changed LESS: " + filepath;
        }))
        .pipe(less())
        .pipe(gulp.dest(paths.build));
});

I've got some other code on the task beside this one but I can reproduce the issue with the task above.
My paths.less_to_compile is a list of strings of paths and paths.build is the build folder.

Might have something to do with the gulp-less package version?

You can see here the output of running my task, I've put some debug code:

captura de ecra 2018-09-14 as 14 02 20

The build prints are the files that exist already on the build folder and have been processed before, the prints are the output of the rename function. The changed less print are the less files that are passed through gulp-less-changed. No matter how many times I run the task, the output is always the same. If I delete the build folder, it will process all the files.

I've managed to find the temp folder and delete it to see if there was any problem with it but I'm still having the same issue.

Ok, I've found the problem. Gulp is not updating the modified time of the file that goes into the build folder after passing through gulp-less-changed, that's why on the next pass, the file passes through again, even though nothing changed.

I've found this gulp-community/gulp-less#301
gulpjs/gulp#2193 (comment)

Ah interesting! Good catch. That is an interesting decision by the Gulp team. If the workaround (setting the mtime manually) helps, I can add that to the documentation.

Well, the workaround won't be needed in the documentation if we can get gulp-less itself fixed instead! Problem is, my patch isn't passing the automated tests, and it's a bit beyond me as to why. I figure that you might be more knowledgeable about it! :) Any hints?

I'm not an expert on how the less project are doing their tests, but based on looking at the Travis build logs I think you have to deal with the case that file is null or undefined, or file.isNull() returns true (and not change the times in those cases).

I can confirm that @WraithKenny 's workaround in the gulp-less repo works. I'll be using that for the moment until this issue is fixed there. I'll close this one since it's not a gulp-less-changed issue.