issue with piping gulp-watch into gulp-ruby-sass - gulp

Maybe I'm an idiot, but I cannot get the combination of gulp-watch and gulp-ruby-sass to work. Any suggestions are hugely welcome. For all the following, the require() calls in my gulpfile.js look like this:
var gulp = require('gulp');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var sass = require('gulp-ruby-sass');
The next bit is what I can't get working. When I change a file I see the output from gulp-watch stating the file was changed, but no output from gulp-ruby-sass and the file isn't written to the dist/ directory.
gulp.task('test-watch', function() {
return watch('./**/*.scss')
.pipe(plumber())
.pipe(sass())
.pipe(gulp.dest('dist/'));
});
Yet I know both gulp-watch and gulp-ruby-sass are setup correctly individually because they work fine on their own:
// writes updated files to dist/ successfully
gulp.task('test-watch', function() {
return watch('./**/*.scss')
.pipe(plumber())
.pipe(gulp.dest('dist/'));
});
// compiles into css and writes to dist/ directory successfully
gulp.src('./**/*.scss')
.pipe(sass())
.pipe(gulp.dest('dist/'));
So what's my problem? Even more vexing, the example above that does not work actually comes from the gulp-watch readme, so should be something that's supported. Any advice is very welcome!

It seems the "solution" is to use gulp-sass for this instead of gulp-ruby-sass.
I still do not know why gulp-ruby-sass doesn't support this since piping the results of gulp.src() into and out of gulp-ruby-sass works like a champ, but it doesn't. I wonder if gulp-watch returns a different file format than gulp.src that gulp-ruby-sass can't handle but gulp-sass can.
If anyone knows how to make this work for gulp-ruby-sass since that's supposedly more fully-featured, please do share.

Related

gulp.watch not detecting change in empty directory

I am working on a simple gulpfile and noticed an issue with gulp.watch method. If I add a new file to an empty directory gulp.watch will not fire. However if there is at least one file in the directory all change events are detected. I could obviously restart my "watch" task every time there is an empty directory added with a new file or I add a file to an existing empty directory but that seems counter intuitive to the purpose of gulp.watch method.
To be clear watch does detect files that are added and deleted only after at least one file exists in that directory.
My question is wether or not this is a bug exclusive to me or if more people have experienced this. Also does anyone know of a current work around?
Here is my gulp task:
gulp.task('watch', () => {
var watcher = gulp.watch('src/styles/scss/*.scss', {cwd: './'}, ['styles']);
watcher.on('change', (event) => {
console.log(`File ${event.path} was ${event.type}, running tasks...`);
});
Current gulp version: 3.9.1
P.S. I also know this may be a limitation of the technology I just don't what to report a bug to the gulp team that isn't a bug.
Thanks!
Awesome! Thank you, Mark for getting me in the right direction. It is not a bug there is just a specific way you have to do it.
gulp.task('watch', () => {
var watcher = gulp.watch(['src/styles/scss/*.scss', 'src/styles/*],{cwd: './'}, ['styles']);
watcher.on('change', (event) => {
console.log(`File ${event.path} was ${event.type}, running tasks...`);
});
The trick is watching your parent directory for any changes. This will now detect file changes as well as added and deleted files in empty subdirectories.

gulp.src is not a function

I want to use gulp to concatenate and then minimize my Javascript files.
But I can not even get the first part to run. I keep getting an error that says "gulp.src is not a function".
I have gulp installed both globally and in the directory I am working with.
And in a different directory I am using gulp to compile my Sass files just fine.
What is wrong with this task?
'use strict';
var gulp = require('gulp'),
concat = require('gulp-concat');
/* Concatenate Javascript files needed to be referenced in the header. */
gulp.task("concatHeaderJS", function() {
gulp.scr([ // what to concat, can also be strings
'inc/js/zebra_dialog.js', // order matters
'inc/js/gx-zebra_dialog.js',
'inc/js/gx-sidebar-nav.js'])
.pipe(concat("header_files_concat.js")) // where to send result
.pipe(gulp.dest("inc/js")); // folder for result to end in
});
Change gulp.scr to gulp.src. It's the typo life.

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).

Gulp + gulp-compass compile, unchanged files being reinjected to BrowserSync

I've got a Gulp task setup to compile .scss files with compass, and also another task running which injects changed CSS into the browser via BrowserSync.
gulp.task('browser-sync', function () {
var options = {
files: './public/css/**/*.css',
proxy: ecs_domain,
port: 3000
};
browserSync(options);
});
gulp.task('compass', function () {
gulp.src('./scss/**/*.scss')
.pipe(compass({
css: cssOutput,
sass: 'scss'
}))
.pipe(gulp.dest(cssOutput))
.pipe(reload({stream: true}));
});
The problem I'm finding is that when compass is run, I get output like in the following snippet:
identical public/css/main.css
[BS] File changed: public/css/main.css
Even though the file main.css hasn't changed, compass somehow touches it, making BrowserSync think it has changed, meaning that even if only one file changes, the entire set of CSS files are re-injected to the browser.
Is there a way to leave the identical/unchanged *.css files un-touch-ed so BrowserSync can only load the files that actually changed?
We have quite a few files and makes the whole process quite slow.
I've found a partial solution. I installed gulp-changed and redirected output from compass to a temporary .out folder. Then created a watch to run gulp-changed when files differ from public/css and .out version using the following task:
gulp.task('copy-changed-css', function () {
gulp.src('.out/**/*.css')
.pipe(changed('public/css', {hasChanged: changed.compareSha1Digest}))
.pipe(gulp.dest('public/css'))
});

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