What were you expecting to happen?
When I change and save partial scss file, gulp should update modified time of main scss file.
What actually happened?
css/
├ _external.scss
â”” main.scss
main.css
gulpfile.js
I edit and save _external.scss, created and updated main.css. But gulp doesn't update modified time of main.css. When I change and save main.scss, gulp updates modified time of main.css.
In other words, gulp will not update modified time of main.css when I edit and save partial scss file. In this case, which is true, specifications or bugs?
Please post a sample of your gulpfile (preferably reduced to just the bit that's not working)
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('style', function() {
return gulp.src('css/main.scss')
.pipe(sass())
.pipe(gulp.dest('./'));
});
gulp.task('watch', function() {
gulp.watch('css/**/*.scss', gulp.series('style'));
});
What version of gulp are you using?
4.0.0
What versions of npm and node are you using?
npm 6.1.0
node 8.9.3 10.5.0
@takamoso Is the resulting file actually changing?
The contents of the file is changed! But modified time don't change.
Gulp 3 works correctly. When partial scss changed, gulp3 update the contents of the file and modified time.
Currently, this is a feature of gulp 4 due to a limitation of node's fs.Stat object. If you need mtime to change - you need to modify the mtime on the files in your pipeline.
If you'd like to help work on a solution for this - we have an open issue at https://github.com/gulpjs/vinyl/issues/105
This may be a little hacky but for those who need a workaround this seems to work
const gracefulFs = require('graceful-fs'),
mapStream = require('map-stream');
// modified version of https://www.npmjs.com/package/gulp-touch
const updateTimestamp = function (options) {
return mapStream(function (file, cb) {
if (file.isNull()) {
return cb(null, file);
}
// Update file modification and access time
return gracefulFs.utimes(file.path, new Date(), new Date(), cb.bind(null, null, file));
});
};
usage
gulp.src(CONFIG.TARGET)
// more pipes here
.pipe(gulp.dest())
.pipe(updateTimestamp());
@colinsanford My current version of that is
const through2 = require( 'through2' );
const touch = () => through2.obj( function( file, enc, cb ) {
if ( file.stat ) {
file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
}
cb( null, file );
});
usage
function sass() {
return gulp.src( sassFiles )
.pipe( sourcemaps.init() )
.pipe( gulpSass() )
.pipe( postcss() )
.pipe( sourcemaps.write() )
.pipe( touch() )
.pipe( gulp.dest( sassDest ) )
.pipe( server.stream() );
}
This updates gulp's file.stat object in pipeline, letting gulp update the file during gulp.dest() instead of a filesystem operation after the fact. It was mentioned that node's fs.stat is lacking, but that seems in regards to something else, and this seems to work fine for this purpose.
I'm using a gulp-touch-cmd plugin implemented in a similar way now.
@takamoso That package does a filesystem touch after the pipeline when gulp has already written the file.
The "gulp way" would be to modify the file.stat and allow .dest() to handle writing the file so we ensure it is efficient and correct.
Most helpful comment
Currently, this is a feature of gulp 4 due to a limitation of node's fs.Stat object. If you need mtime to change - you need to modify the mtime on the files in your pipeline.
If you'd like to help work on a solution for this - we have an open issue at https://github.com/gulpjs/vinyl/issues/105