Rebuild all files if template changes - gulp

I'm using gulp to convert markdown files to HTML, and using the gulp-watch plugin (not the gulp.watch API function) to rebuild files if they change. Works great!
gulp.task('markdown', function () {
gulp.src('src/**/*.md')
.pipe(watch('src/**/*.md'))
.pipe(markdown())
.pipe(template('templates/md.tpl'))
.pipe(gulp.dest('dist'));
});
The problem is that the pipeline src is the markdown files, but within the pipeline I also reference a template file. If that template changes, all the markdown files need to be rebuilt. Is there a way to express that dependency in gulp/gulp-watch?
I tried using gulp.watch (the API function) to watch the template and run the 'markdown' task if it changes ...
gulp.watch('templates/md.tpl', ['markdown']);
... but that didn't work. Nothing happens. I assume having gulp-watch in the pipeline prevents it from doing anything.
I guess I could create a two tasks, one with gulp-watch and one without, and use the one without to force a full rebuild. I'd rather not, because then it becomes an ongoing problem to keep the two in sync.
Is there a better way?

I guess I could create a two tasks, one with gulp-watch and one without, and use the one without to force a full rebuild. I'd rather not, because then it becomes an ongoing problem to keep the two in sync.
Remember, gulp is just JavaScript.
Simply write a function that constructs the stream with or without the watch() step depending on a parameter that you pass. The gulp-if plugin let's you write something like this in a very concise way (although it's not necessary and could be done without it).
Here's how I would do it:
var gulpIf = require('gulp-if');
function processMarkdown(opts) {
gulp.src('src/**/*.md')
.pipe(gulpIf(opts.watch, watch('src/**/*.md')))
.pipe(markdown())
.pipe(template('templates/md.tpl'))
.pipe(gulp.dest('dist'));
}
gulp.task('markdown', function() {
processMarkdown({watch: true});
watch('templates/md.tpl', function() {
processMarkdown({watch: false});
});
});

You can specify gulp src as an array, too:
gulp.src(['src/**/*.md', 'templates/md.tpl'])

Related

Script Concat / Minify Task Keeps Running

So I have a task like so:
gulp.task('scripts', function() {
return gulp.src(['app/scripts/app.js', 'app/scripts/controllers/**/*.js', 'app/scripts/services/**/*.js', 'app/scripts/directives/**/*.js', 'app/scripts/libs/**/*.js' ])
.pipe(concat('external.min.js'))
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(gulp.dest('app/scripts'))
.pipe(gulp.dest('dist/scripts'))
});
and I have a watch task:
gulp.task('watch', ['sass-dev', 'scripts'], function() {
gulp.watch('app/style/sass/**/*.scss', ['sass-dev']);
gulp.watch('app/scripts/**/*.js', ['scripts']);
});
All works well, except whenever I save a JS file, "scripts" runs multiple times. I'm assuming the problem lies with the gulp.src and it looking at multiple files, but I'm not sure.
This is no big deal (to me), but sometimes I'll swap over to the command line and the task is running infinitely. It just keeps getting called over and over again.
If you haven't already guessed, I'm running Angular, which is why app.js is first and I have ngAnnotate.
Can someone shed some light on why the script runs continuously sometimes?
I guess the problem is .pipe(gulp.dest('app/scripts')). You're doing some stuff (uglify and angular stuff) with your scripts and then you place them in the same folder you're watching. So the scripts task will launch again and again and again.
You should remove this line and only place your distribution scripts in your distribution folder and leave your app files untouched.

GULP: Modify a watched file in place without causing an infinite loop

Im trying to use gulp and jscs to prevent code smell. I also want to use watch so that this happens when ever a change is made. The problem I'm running into is jscs is modify the source file that is being watched. This causes gulp to go into an infinite loop of jscs modifying the file and then watch seeing the change and firing off jscs again and again and again ...
const gulp = require('gulp');
gulp.task('lint', function() {
return gulp.src('/src/**/*.js')
.pipe(jscs({
fix: true
}))
.pipe(jscs.reporter())
.pipe(gulp.dest('/src'));
});
gulp.task('watch', function() {
gulp.watch('/src/**/*.js', ['lint']);
});
It's generally a bad idea to override source files from a gulp task. Any Editors/IDEs where those files are open might or might not handle that gracefully. It's generally better to write the files into a separate dist folder.
That being said here's two possible solutions:
Solution 1
You need to stop the gulp-jscs plugin from running a second time and writing the files again, thus preventing the infinite loop you're running into. To achieve this all you have to do is add gulp-cached to your lint task:
var cache = require('gulp-cached');
gulp.task('lint', function() {
return gulp.src('/src/**/*.js')
.pipe(cache('lint'))
.pipe(jscs({
fix: true
}))
.pipe(cache('lint'))
.pipe(jscs.reporter())
.pipe(gulp.dest('/src'));
});
The first cache() makes sure that only files on disk that have changed since the last invocation of lint are passed through. The second cache() makes sure that only files that have actually been fixed by jscs() are written to disk in the first place.
The downside of this solution is that the lint task is still being executed twice. This isn't a big deal since during the second run the files aren't actually being linted. gulp-cache prevents that from happening. But if you absolutely want to make sure that lint is run only once there's another way.
Solution 2
First you should use the gulp-watch plugin instead of the built-in gulp.watch() (that's because it uses the superior chokidar library instead of gaze).
Then you can write yourself a simple pausableWatch() function and use that in your watch task:
var watch = require('gulp-watch');
function pausableWatch(watchedFiles, tasks) {
var watcher = watch(watchedFiles, function() {
watcher.close();
gulp.start(tasks, function() {
pausableWatch(watchedFiles, tasks);
});
});
}
gulp.task('watch', function() {
pausableWatch('/src/**/*.js', ['lint']);
});
In the above the watcher is stopped before the lint task starts. Any .js files written during the lint task will therefore not trigger the watcher. After the lint task has finished, the watcher is started up again.
The downside of this solution is that if you save a .js file while the lint task is being executed that change will not be picked up by the watcher (since it has been stopped). You have to save the .js file after the lint task has finished (when the watcher has been started again).

VS 2015 Use Gulp to Compile Less

I am trying to set up a similar process to what Web Essentials offered in the old visual studio in the newest one. For those of you who aren't familiar with how that worked, the process was:
File Setup:
a.less
a.css
a.min.css
a.css.map
b.less
b.css
b.min.css
b.css.map
So basically when you open a.less and start editing it, it would automatically check out a.css, a.min.css, and a.css.map as well. Then when you save, it would recompile the 3 sub files as well as saving the less file.
I am able to replicate this by writing a separate task for each file like so:
gulp.task('checkout', function () {
return gulp.src('Styles/brands.css')
.pipe(tfs());
});
gulp.task('less', ['checkout'], function () {
del('Styles/brands.css');
return gulp.src('Styles/brands.less')
.pipe(less())
.pipe(gulp.dest('Styles'));
});
This uses gulp-tfs-checkout to checkout the sub file, and then the less to compile. This works 100% how I expect it to. I can set up a watch to watch the less task and everything will work great. The only problem is, how do I expand this to handle all my less files in that folder? I could write separate checkout and compile tasks for each file, but that's not really ideal.
I am used to writing projects where saving any less file compiles and concats all of them into a single or a couple files, but this is a work project and for multiple reasons I need to keep the css files separate as they are now. We use visual studio's bundling, but its an older project and people have referenced the css files randomly outside of the bundling process so it would be a pretty big/risky task to change that.
I don't know how to watch many files, but only change the current one if that makes sense.
gulp.task('less', function () {
return gulp.src('Styles/*.less') //watch all of my files
.pipe(tfs())//checkout only the css file for the less file that was changed here somehow
.pipe(less()) //compile only the css file that was changed
.pipe(gulp.dest('Styles'));
});
I am fairly used to grunt and gulp, but like I said I generally do things in bulk on my project. I'm not sure how to do this when I want to watch all the files, but only change 1
Why don't you create all those tasks per each file dynamically? You can read the contents of the folder where your less files are with fs.readdirSync and then if the file is a less file you create for each the task 'checkout' + filename and then 'less' + filename.
Being dynamically you will not have any problems when you create a new less file or when you remove one.

gulp performing task multiple times

I have the following code fragment in my gulpfile.
gulp.task('static', function() {
return gulp.src(['./src/**', '!./src/js/**', '!./src/js/', '!./src/scss/', '!./src/scss/**'])
.pipe(gulp.dest(outputDir + '/'))
});
gulp.task('watch', function() {
gulp.watch(['./src/**', '!./src/js/**', '!./src/js/', '!./src/scss/', '!./src/scss/**'], ['static']);
});
gulp.task('dev', ['static']);
gulp.task('default', ['watch', 'dev']);
If I run gulp dev, gulp watch or gulp static, everything works fine. However, if I run just gulp (default), it does the static task 5 times. Can anyone help me out with why this is happening?
P.S. The paths passed to watch are such because if I don't disclude the directories as separate paths, it seems to be copying the empty directories js and scss for some reason.
Probably because you're not returning the tasks, and you need them to be asyc.
See this: Gulp.js task, return on src?
and the docs (also linked in SO post above) https://github.com/gulpjs/gulp/blob/master/docs/API.md#async-task-support
Also, the dev task looks redundant in its current form - you may as well use the task static directly, unless you plan to bundle in more tasks with dev

gulp-watch breaks when new files are added

I'm using gulp-watch plugin and would like to copy newly added files in the source to the target destination.
watch({glob:SOURCE + '/**/*.js'})
.pipe(plumber())
.pipe(gulp.dest(DESTINATION));
Every time a new file is added into the SOURCE directory I get "Bus error: 10" and the watch breaks without copying the newly added file.
Please you this syntax for adding new files in gulp
gulp.task('task_name', function() {
return watch({
glob: SOURCE
}, function(files) {
return files.pipe(plumber()).pipe(jade()).pipe(gulp.dest(DESTINATION));
});
});
gulp.watch doesn't create a source stream, it triggers on file changes and calls tasks.
Try creating a simple move task alongside a watch task, then trigger the move from the watch. Something like this:
gulp.task('move-js', function() {
gulp.src('./js-src/**/*.js')
.pipe(gulp.dest('./js-dest'));
});
gulp.task('watch-js', ['move-js'], function() {
gulp.watch('./js-src/**/*.js', ['move-js']);
});
Note that the watch-js task has move-js as a dependency, this will call the move task whenever the watch is invoked, rather than waiting for something in the watched directory to change.
I repeated the glob for clarity, but that should probably be stored in a variable.