Samuel Oloruntoba
This tutorial is out of date and no longer maintained.
Developers are a lazy bunch. Or at least I assume we are. Because of this reason we tend to build tools that make our work faster. From highly customizable editors to task runners.
With gulp, we can build tasks that automatically compile Sass, start a Laravel server, live reload the browser, transpile ES6 to ES5, etc.
Thankfully, there are a few languages out there like Javascript which is very forgiving. Nonetheless, mistakes can happen.
Since we have a “gulp watcher” that watches our project and runs defined tasks when we make any change, an error can easily break our pipeline.
Watching in Gulp refers to triggering a task when a change is made to a project’s source.
So, before we watch a task, let’s create a task that we will use as our example throughout this tutorial. The task we will create is a SCSS compilation task.
We can create a new working directory, name it whatever you want. We can now create our gulpfile.js
in our working directory. Then we add our build task. Before we define our task, we need to install our dependencies.
For this article, here is a list of our dependencies.
{
"private": true,
"devDependencies": {
"gulp": "^3.9.1",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.1.0",
"gulp-sass": "^2.3.2",
"gulp-util": "^3.0.7"
}
}
Now that we have our dependency list, we can run npm install
or if you have the new yarn package manager based on npm, you can run yarn install
.
In the gulpfile, we can then define our gulp task.
const gulp = require('gulp');
const sass = require('gulp-sass');
gulp.task('compile-scss', function () {
gulp.src('scss/main.scss')
.pipe(sass())
.pipe(gulp.dest('css/'));
});
So from the command line, we can run gulp compile-scss
and our Sass file should be compiled.
Now that we have a task defined, let’s trigger the file whenever we make a change to the project’s source.
gulp.task('watch', function () {
gulp.watch('scss/**/*.scss', ['compile-scss']);
});
From the terminal, we can run gulp watch
and whenever a file ending with .scss
extension in any folder within the scss
directory gets changed, compile-scss
task is run.
We’ve got our task and watcher up and running, but if an error occurs in our SCSS file, the gulp watcher gets terminated. We then have to go back to the terminal and type gulp watch
again. This gets very annoying really fast. A silly little ;
can break our watcher.
To avoid breakage like this, we can one of three things:
One a way to go about dealing with errors is to “swallow the error”. The error(s) will be taken in by the application to prevent the task from breaking. Basically, errors will not be reported and the task will keep running.
Since gulp sends a lot of events, we can hook into the error event of the task we don’t want to fail.
gulp.task('compile-scss', function () {
gulp.src('scss/main.scss')
.pipe(sass())
.on('error', function (err) {
console.log(err.toString());
this.emit('end');
})
.pipe(gulp.dest('css/'));
});
As you can see above, from the on
listener on the task. The on
event listener takes in two parameters: the event and a function to be triggered when the event gets called. The function that gets called takes in the error object. We then log the stringified version of the error to the terminal.
It is absolutely important to this.emit('end')
, if this event is not triggered, the next pipe in this task pipeline never gets called, and the buffer will be left open.
This method involves using the gulp-util plugin.
The gulp-util plugin provides a lot of helpful methods, one of them is log
. With this method, we can log the error to the terminal. To use this, we attach an error event listener to the pipe.
var gutil = require('gulp-util');
gulp.task('compile-scss', function () {
gulp.src('scss/main.scss')
.pipe(sass())
.on('error', gutil.log)
.pipe(gulp.dest('css/'));
});
But this method also requires us to go through each pipe in the pipeline and attach .on('error', gutil.log)
listener to all tasks. Something like this.
gulp.task('compile-scss', function () {
gulp.src('scss/main.scss')
.pipe(sass())
.on('error', gutil.log)
.pipe(autoprefixer())
.on('error', gutil.log)
.pipe(gulp.dest('css/'));
});
Out of all three methods, this is my favorite. With gulp-plumber, we don’t need to go to each pipe and add a listener, we can just add a global listener to the task and have a meaningful error displayed.
var plumber = require('gulp-plumber');
gulp.task('compile-scss', function () {
gulp.src('scss/main.scss')
.pipe(plumber())
.pipe(sass())
.pipe(autoprefixer())
.pipe(cssnano())
.pipe(gulp.dest('css/'));
});
We can have multiple pipes in this task and still only ever need to call plumber once.
Now that we can see the errors without breaking out of watch, we need to find a way to get some kind of notification when an error occurs. There are several ways to do this, but I will cover only one method.
The method I will cover in this article: will play a beeping sound when an error occurs, and also show a system notification that looks like this.
This notification looks different according to your operating system.
To get this feature to work, we need to extend the gulp-plumber plugin. So in our gulp task, we update our call to plumber.
gulp.task('scss', function () {
gulp.src('scss/main.scss')
.pipe(plumber({ errorHandler: function() {
// do stuff here
}}))
.pipe(sass())
.pipe(gulp.dest('css'));
});
Notice, we pass an object that has an errorHandler
property that takes a closure to plumber. We can then call our notify plugin in that closure.
var notify = require('gulp-notify');
gulp.task('scss', function () {
gulp.src('scss/main.scss')
.pipe(plumber({ errorHandler: function(err) {
notify.onError({
title: "Gulp error in " + err.plugin,
message: err.toString()
})(err);
}}))
.pipe(sass())
.pipe(gulp.dest('css'));
});
We call the notify plugin and pass it an object that has a title
and message
property. Now, when an error occurs, a notification is triggered. To play a beeping sound, we can use **gulp-util ** for that.
var notify = require('gulp-notify');
gulp.task('scss', function () {
gulp.src('scss/main.scss')
.pipe(plumber({ errorHandler: function(err) {
notify.onError({
title: "Gulp error in " + err.plugin,
message: err.toString()
})(err);
// play a sound once
gutil.beep();
}}))
.pipe(sass())
.pipe(gulp.dest('css'));
});
Now, when an error occurs, we get both sound and system notification, and then you can check your terminal for more information.
The configuration in this article should be suitable for most users, but if you have any suggestions/improvements, please let us know in the comments.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!