I want to compile only the .less files that have changed in order to speed up my debug/coding workflow.
Here is my gulp task:
gulp.src('core/**/*.less')
.pipe(changed('core'))
.pipe(less().on('error', handleError))
.pipe(autoprefixer('last 2 version'))
.pipe(remember())
.pipe(concat('main.min.css'))
.pipe(gulp.dest('core'))
.on('end', resolve)
.on('error', reject);
I used gulp-changed and because it didn't work at first, I tried to use gulp-remember as well, but with no effect. The watch works, it compiles super fast, but it has no effect at all.
If I remove changed('core') and remember() it works, but it's slower (around 16 seconds).
gulp-changed is a poor fit for your use case, since it is meant to compare input files with output files on disk.
Say you have an input file core/foo/bar.less that you pipe through changed('dist'). What this does is to look for an output file dist/foo/bar.less. If the input file is newer than the output file, it is passed through. Otherwise it is filtered out.
That means using changed('core') cannot possibly work. It compares the input file core/foo/bar.less with the output file core/foo/bar.less. But they're the same file. That means the input file can never be newer than the output file and is never passed through.
There's another problem. You don't have one output file for each input file. All your .less files are compiled into one main.min.css file. While you can make this work using a custom comparator it doesn't work out of the box.
What you actually want is gulp-cached. Instead of comparing each input file with an output file on disk it compares each input file with a previous version of the same file that has been cached in memory.
var cached = require('gulp-cached');
gulp.task('css', function() {
return gulp.src('core/**/*.less')
.pipe(cached('less'))
.pipe(less())
.pipe(autoprefixer('last 2 version'))
.pipe(remember('less'))
.pipe(concat('main.min.css'))
.pipe(gulp.dest('core'));
});
Related
I'm trying to write a gulp plugin for the first time. The plugin is later supposed to validate some styleguide requirements for all css and js files in a project.
In order to properly debug the plugin while testing, I want to use gutil.log() for printout. To get started, I created a gulp plugin which simply outputs the path of the tested file.
module.exports = function(){...};
function validate(file) {
gutil.log(gutil.colors.yellow(file.path));
};
However, only one filename is printed in the gulp output. Debug shows, that all the correct files are listed with gulp.src(), but there is always only log output for a single file.
I then found the following here: Handle multiple files in a Gulp plugin
I tried using gulp-foreach with the following code:
gulp.task('head', function () {
return gulp.src('./src/app/**/*.{css,js}')
.pipe(foreach(function (stream, file) {
return stream
.pipe(validate());
}));
});
But the result remains the same,there is only one log entry. I feel like I'm missing something very obvious here...
I'm trying to come up with a gulp task that generates new source maps whenever its corresponding .js file has changed, this is what I have so far:
gulp.task('maps', [ 'compile:ts' ], function () {
return gulp.src([
'app/**/*.js'
])
.pipe(newer({ dest: 'app', ext: '.js.map' }))
.pipe(print(function (filepath) {
return 'Creating source map for ' + filepath + '...';
}))
.pipe(sourcemaps.init())
.pipe(sourcemaps.write('./'))
.pipe(print(function (filepath) {
return 'Writing source map for ' + filepath + '...';
}))
.pipe(checkout())
.pipe(gulp.dest('app'))
;
});
Now two weird things happen:
gulp-newer returns all .js files, it doesn't matter if they were changed or not (regarding the timestamps of the .map.js files).
gulp-sourcemaps emits both, the .js and the .js.map file.
Can anyone provide a hint what I'm missing here?
gulp-sourcemaps emits both, the .js and the .js.map file.
That's to be expected, because that's how source maps work. Each .js file contains a sourceMappingURL comment that points to the .js.map file so your browser knows where to find it.
You can leave this out by using the addComment option:
.pipe(sourcemaps.write('./'), {addComment:false})
Of course, that means your HTTP server has to send a X-SourceMap header for each .js file.
gulp-newer returns all .js files, it doesn't matter if they were changed or not (regarding the timestamps of the .map.js files).
This might be caused by gulp-sourcemaps emitting both a .js and a .js.map file, effectively overwriting your existing .js file. Using the same source and destination directories is generally a bad idea, so using a different dest directory would solve this problem.
(It might also be caused by the checkout() pipe, but you didn't describe what that does. I'd try removing this and see if it works.)
However I don't think any of the above really matters, since your general approach and the way you're using gulp-sourcemaps is likely to be completely wrong. I assume you want sourcemaps from your original .ts files to your compiled .js files. In that case you need to use it in your compile:ts task. The way you're using it now will just produce an empty source map file.
I'm new to gulp and I tried to follow the documentation in https://www.npmjs.com/package/gulp-newer to understand how it works. However its not working as expected for the below task. I think I'm missing something obvious.
Here's the folder structure,
temp
file1.js
file2.js
new
file1.js
file3.js
change
<empty initially>
I want to compare temp folder with new folder and if there are any new files in new folder(which was not present in temp earlier) then move those files to change folder. This is just me trying to understand how gulp-newer works. Am I doing it right?
gulp.task('newer', function() {
return gulp.src('temp/*.js')
.pipe(newer('new/*.js'))
.pipe(gulp.dest('change'))
});
However when I run this task it just copy all the files in temp folder to change folder. So after task run change folder has file1.js and file2.js. I'm expecting just file3.js to be present in change(since that's a new file). Correct me if my understanding with the approach is incorrect.
From gulp-newer:
Using newer with many:1 source:dest mappings Plugins like gulp-concat
take many source files and generate a single destination file. In this
case, the newer stream will pass through all source files if any one
of them is newer than the destination file. The newer plugin is
configured with the destination file path.
and the sample code:
var gulp = require('gulp');
var newer = require('gulp-newer');
var concat = require('gulp-concat');
// Concatenate all if any are newer
gulp.task('concat', function() {
// Add the newer pipe to pass through all sources if any are newer
return gulp.src('lib/*.js')
.pipe(newer('dist/all.js'))
.pipe(concat('all.js'))
.pipe(gulp.dest('dist'));
});
it seems that you need to pass in all the files already concatenated to newer. In your case:
gulp.task('newer', function() {
return gulp.src('temp/*.js')
.pipe(newer('new/*.js'))
.pipe(concat('*.js'))
.pipe(gulp.dest('change'))
});
Also, since newer checks the files modified date make sure that the files are actually newer. I know it's obvious, but I'm usually stuck on "obvious" stuff.
May I also suggest gulp-newy in which you can manipulate the path and filename in your own function. Then, just use the function as the callback to the newy(). This gives you complete control of the files you would like to compare.
This will allow 1:1 or many to 1 compares.
newy(function(projectDir, srcFile, absSrcFile) {
// do whatever you want to here.
// construct your absolute path, change filename suffix, etc.
// then return /foo/bar/filename.suffix as the file to compare against
}
My default task is to execute the "step2" task, which depends on step1. Step1 copies over a bunch of files, step2 is supposed to rename a single file, "file1.txt". My default task says to just do "step2". I am using gulp-rename.
gulp.task('step1', function() {
var files = [
'./folder1/**/*.*',
'./file1.txt'
];
return gulp.src(files, {base: "."})
.pipe(gulp.dest("./build"));
});
gulp.task('step2', ['step1'], function() {
gulp.src('./build/file1.txt')
.pipe(rename("./renamed-file1.txt"))
.pipe(gulp.dest("./build"));
});
The problem is I don't see a renamed file at all, and instead I see both the copy of the file I copied over and the renamed file. How do I fix this?
Also, why is it that for "./renamed-file1.txt", I have to specify it that way to ensure it gets in the build directory as opposed to ./build/renamed-file1.txt?
The gulp-rename plugin renames the files in the stream not the ones in the file system: I guess you should split your step1 in to 2 gulp flows renaming your file while copying it.
I currently use gulp for most of my automation tasks. To keep the process optimised I check for file changes before processing the file. The problem is that when I rebuild my files and only a single file in the set has changed, the concat file only includes the changed file. Is there a way to pickup all the files in case of concat
gulp.task('myScripts', function() {
return gulp.src(['public/js/one.js','public/js/two.js'], {base: 'public/js'})
.pipe(changed('public/dist/original/js'))
.pipe(gulp.dest('public/dist/original/js'))
.pipe(uglify())
.pipe(concat('all.min.js'))
.pipe(gulp.dest('public/dist/js'));
});
I am using gulp-changed to check for file changes, Here are the scenarios:
When running it for the first time, it takes both the miles and minifies them.
When only one file is changed after that, the concatenated file 'all.min.js' only contains the minified version of the changed file.
Can anyone please help me with how I can concat all the files even if only one file changes?
You should require gulp-remember and call it before concat. Gulp-remember works with gulp-changed and restores the previous changed files into the stream.
Have a look to this official recipe: Incremental rebuilding, including operating on full file sets