gulp-sass, watch stops when invalid property name - node.js

watch stops when error messages occur.
stream.js:94
throw er; // Unhandled stream error in pipe.
^
source string:51: error: invalid property name
How I can keep watch running and just to tell me where is the error located.
grunt could deal with errors and doesn't need to stop,
styleSheet.scss:41: error: invalid property name
otherwise, I need to keep typing "gulp" in the command-line when an error occurs.

This answer has been appended to reflect recent changes to Gulp. I've retained the original response, for relevance to the OPs question. If you are using Gulp 2.x, skip to the second section
Original response, Gulp 1.x
You may change this default behavior by passing errLogToConsole: true as an option to the sass() method.
Your task might look something like this, right now:
gulp.task('sass', function () {
gulp.src('./*.scss')
.pipe(sass())
.pipe(gulp.dest('./'));
});
Change the .pipe(sass()) line to include the errLogToConsole: true option:
.pipe(sass({errLogToConsole: true}))
This is what the task, with error logging, should look like:
gulp.task('sass', function () {
gulp.src('./*.scss')
.pipe(sass({errLogToConsole: true}))
.pipe(gulp.dest('./'));
});
Errors output will now be inline, like so:
[gulp] [gulp-sass] source string:1: error: invalid top-level expression
You can read more about gulp-sass options and configuration, on nmpjs.org
Gulp 2.x
In Gulp 2.x errLogToConsole may no longer be used. Fortunately, gulp-sass has a method for handling errors. Use on('error', sass.logError):
gulp.task('sass', function () {
gulp.src('./sass/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
If you need more fine-grained control, feel free to provide a callback function:
gulp.task('sass', function () {
gulp.src('./sass/**/*.scss')
.pipe(sass()
.on('error', function (err) {
sass.logError(err);
this.emit('end');
})
)
.pipe(gulp.dest('./css'));
});
This is a good thread to read if you need more information on process-control: https://github.com/gulpjs/gulp/issues/259#issuecomment-55098512

Actually above anwsers doesn't work for me (Im using gulp-sass 3.XX). What really worked:
gulp.task('sass', function () {
return gulp.src(config.scssPath + '/styles.scss')
.pipe(sourcemaps.init())
.pipe(sass({ outputStyle: 'compressed' })
.on('error', sass.logError)
)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(config.cssPath))
});
In gulp-sass 3.x.x when I was using "sass.logError(err);" I constantly recive error that "this.emit('end'); is not a function". Now when I'm using:
.pipe(sass({ outputStyle: 'compressed' })
.on('error', sass.logError)
)
everything is working like a charm

In gulp "^2.0.0" the option errLogToConsole will no longer work. Instead gulp-sass has a built in error logging callback that uses gulp-util under the hood. Also, because gulp has some problems with killing the process on errors, if you are using with watch you will have to call this.emit('end')
https://github.com/gulpjs/gulp/issues/259#issuecomment-55098512
var sass = require('gulp-sass');
//dev
sass(config.sassDev)
.on('error', function(err) {
sass.logError(err);
this.emit('end'); //continue the process in dev
})
)
//prod
sass(config.sassProd).on('error', sass.logError)

A heads up for Gulp 3 users:
I liked #dtotheftp solution above, regarding gulp 2.x. Interestingly, it doesn't work unter Gulp3, at least not under #3.9.1:
.on('error', function(err){
sass.logError(err);
this.emit('end'); //continue the process in dev
})
gets me
TypeError: this.emit is not a function
at Function.logError (/depot/myproject/node_modules/gulp-sass/index.js:181:8)
Note, that the complaint is not coming from his this.emit() in the gulpfile but rather from the sass node-module, hence from the prior line.
This works for me:
.on('error', function(err){
gutil.log(err);
this.emit('end');
})
I do get all errors², and the watch never ends ;) (I am also using plumber() right after gulp.src(), which might help with that).
(Yes, the fix might be highly illogical, since sass.logError is said to be based on gutil...)
—
²also on undefined macros which went silent before on my setup for whatever reason.

Related

How to stream sass into browserSync without Gulp?

I am trying to stream sass into browsersync without gulp. Here is my code
function streamSass() {
dev.sassTasks.forEach(task => {
const sass = new Sass(task.src, task.dest, task.opts)
sass.write().then(() => {
const stream = fs.createReadStream(sass.dest.segments.absolutePath)
stream.pipe(browserSync.stream())
})
})
}
The Sass class just process and creates css file. When the function executed nothing happens on the side of the browsersync. Why is that? Assume that browsersync is running and is active when function is executed.
If you are not seeing anything happen then I would wager that there is something wrong with your stream as it will not throw an error and without an event handler it will silently fail.
Try adding an error event handler:
stream.on('error', err => console.log(err));

Running gulp tasks in sequence throws `Unhandled stream error in pipe`

I have a gulp task as following :
gulp.task('build-files, function(cb) {
runSequence('run-build-cmd',
'delete-dest', 'copy-files',
cb);
});
This task is running whenever something changed in a source folder as following :
gulp.watch(pathToSrcFolder, ['build-files']);
So this task runs 3 other gulp tasks in the specified order, the first one it runs a build command, the second one will delete a folder as following :
gulp.task('delete-dest', (cb) => {
del([pathToDestFolder], {force: true});
cb();
});
and the third one will copy files from a source into two destinations :
gulp.task('copy-files', () => {
return gulp.src(pathToSrcFolder)
.pipe(gulp.dest(pathToDestFolder))
.pipe(gulp.dest(anotherPath));
});
Please notice that the pathToDestFolder is the same folder in both delete-source and copy-files commands.
The problem I had running this sequence, is this error:
internal/streams/legacy.js:59
throw er; // Unhandled stream error in pipe.
^
Error: ENOENT: no such file or directory, chmod 'pathToDestFolder\path\to\some\file\file.ext'
I don't know why I'm getting this error.
And when I run the gulp delete-dest in cmd prompt (which will clear the pathToDestFolder) and then gulp copy-files (which will copy the source folder into two folders pathToDestFolder and anotherPath) it works as expected .
So I guess runSequence didn't work as expected ? if so, how can I solve this ?
Edit:
I tried to use rimraf instead of del, and all seems to work just fine, I know that rimraf is depricated, and it's better to use del instead, but why del in this case results in an exception ?
Edit 2:
Instead of using rimraf as a solution, I tried this solution:
gulp.task('delete-dest', (cb) => {
del([pathToDestFolder], {force: true})
.then(paths => {cb();});
});
And it worked like magic.
Why this worked instead ? I don't know !
If someone can clarify things I would be greatful.
If you look here, you'll find that del returns a promise. It's an async method.
In your code, you call the cb() right after calling del(...), but before del actually finishes deleting the directory.
That's why you have to execute the callback after chaining with then:
gulp.task('delete-dest', (cb) => {
del([pathToDestFolder], {force: true})
.then(paths => {cb();});
});
And then your operations will run in the correct order.
The error you were getting before is the result of things being run in a weird order, leading to weird behavior. Gulp is trying to copy to a directory while the file system is deleting it, and that conflict leads to a file system error.
As an experiment, you can try running the synchronous version of del like so:
gulp.task('delete-dest', (cb) => {
del.sync([pathToDestFolder], {force: true});
cb();
});
See if that works (though you should prefer the async version).
As a side note, unless this is a feature of Gulp 4 though probably not, rather than calling a callback in your task, you can just return a promise like so:
gulp.task('delete-dest', () => {
return del([pathToDestFolder], {force: true});
});
That will tell Gulp that your task is finished, and it can move on to the next.

sourceComment in Gulp is showing path relative to computer, rather than folder

I have been doing sourceComments for a project I am working with and the comments that get outputted in the CSS so that I can find the correct scss file are showing paths that are relatvie to my computer
e.g.
/* line 39, /Applications/MAMP/htdocs/usaa/bare-minimum/framework/scss/settings/_typography.scss */
I would like this to be
/* line 39, settings/_typography.scss */
How would I accomplish this when this is my gulpfile.js (showing here the sass function)
var sassSrc = './framework/scss/*.scss';
var watchSrc = './framework/**/*.scss';
function doSass(cb) {
gulp.src([sassSrc, watchSrc], {
base: 'framework/scss'
})
.pipe(sourcemaps.init())
.pipe(sass({
errLogToConsole: true,
soureMap: 'scss',
sourceComments: 'map'
}).on('error', sass.logError))
.pipe(cmq())
.pipe(autoprefixer())
.pipe(sourcemaps.write())
.pipe(gulp.dest('dev/css/'))
.pipe(cssmin())
.pipe(rename({
extname: '.min.css'
}))
.pipe(gulp.dest('dev/css/'))
.on('end', function() {
if (cb && typeof cb === 'function')
cb();
});
}
gulp.task('sass', doSass);
Unfortunately it's not possible with LibSass. Answer from node-sass member:
With sourceComments option, libsass emits diagnostics information for each selector it encounters.
It is supposed to be a raw debug info, hence the paths are not (relatively) resolved.
On a more serious note, this info emerges from core abstract syntax tree, where resolving canonical file paths will slow down the performance of the overall compilation.
For the browser dev tools aid, please use sourceMap option instead, as source-map carries relative paths.
Link to Github discussion
Discussion on libsass: Link

Gulp streams not supported Error using gulp-istanbul

I'm getting an error with streams.
I'm working on adding istanbul to my existing mocha task. When I run this task I get the error below.
I'm using gulp-istanbul
(note: the config.test.src.bdd.features is set to the value 'test/bdd/features/**/*-spec.js')
var stream = gulp.src([config.test.src.bdd.features], { read: false });
gulp.task('mocha-bdd-features', function(cb) {
process.env.PORT = 8001;
return stream
.pipe(istanbul())
.pipe(istanbul.hookRequire())
.pipe(mocha({
compilers: {
js: babel
},
reporter: config.test.mocha.reporter,
ui: 'bdd'
}))
.on('finish', function () {
stream.pipe(istanbul.writeReports())
stream.pipe(istanbul.enforceThresholds({thresholds: {global: 90}}))
stream.on('end', cb);
});
});
the error I get is:
events.js:85
throw er; // Unhandled 'error' event
^
Error: streams not supported
and who knows I may not be setting up this task right when trying to incorporate gulp-istanbul but trying to at least get past this error first.
I was facing the exact same issue.
I believe the problem is in line:
var stream = gulp.src([config.test.src.bdd.features], { read: false });
Setting the read option to false causes the file.contents to be null and therefore istanbul is not able to cover the files. (check here)
so try the same thing but without the read option.
var stream = gulp.src([config.test.src.bdd.features]);
Hope this helps.

Is it possible to run the grunt command after a yeoman generator install?

Basically I'd like to run grunt after my generator finishes installing dependencies, I found that you can add a callback function to the installDependencies method to run after everything has been installed like this:
this.on('end', function () {
this.installDependencies({
skipInstall: options['skip-install'],
callback: function () {
console.log('All done!');
}
});
});
However I'm not sure how to run the grunt task (as in going to the terminal and running "grunt")
After this.on('end') add this lines
// Now you can bind to the dependencies installed event
this.on('dependenciesInstalled', function() {
this.spawnCommand('grunt', ['build']);
});
check this topic for more details.
But if you're using the latest update of yeomen, you'll need to make it like this
this.on('end', function () {
if (!this.options['skip-install']) {
this.npmInstall();
this.spawnCommand('grunt', ['prepare']); // change 'prepare' with your task.
}
});

Resources