Skip to content

Commit

Permalink
Docs: Integrate pump documentation from gulp-uglify (closes #1791)
Browse files Browse the repository at this point in the history
  • Loading branch information
terinjokes authored and phated committed Jun 18, 2017
1 parent a0ec3ff commit 45adfc3
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* [API documentation](API.md) - Learn the ins and outs of using gulp
* [CLI documentation](CLI.md) - Learn how to call tasks and use compilers
* [Writing a Plugin](writing-a-plugin/README.md) - So you're writing a gulp plugin? Go here for the essential dos and don'ts.
* [Why Use Pump?](why-use-pump/README.md) - Why you should use the `pump` module instead of calling `.pipe` yourself.
* [Spanish documentation][SpanishDocs] - gulp en Español.
* [Simplified Chinese documentation][SimplifiedChineseDocs] - gulp 简体中文文档.
* [Korean documentation][KoreanDocs] - gulp 한국어 참조 문서.
Expand Down
122 changes: 122 additions & 0 deletions docs/why-use-pump/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Why Use Pump?

When using `pipe` from the Node.js streams, errors are not propagated forward
through the piped streams, and source streams aren’t closed if a destination
stream closed. The [`pump`][pump] module normalizes these problems and passes
you the errors in a callback.

## A common gulpfile example

A common pattern in gulp files is to simply return a Node.js stream, and expect
the gulp tool to handle errors.

```javascript
// example of a common gulpfile
var gulp = require('gulp');
var uglify = require('gulp-uglify');

gulp.task('compress', function () {
// returns a Node.js stream, but no handling of error messages
return gulp.src('lib/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
```

![pipe error](pipe-error.png)

There’s an error in one of the JavaScript files, but that error message is the
opposite of helpful. You want to know what file and line contains the error. So
what is this mess?

When there’s an error in a stream, the Node.js stream fire the 'error' event,
but if there’s no handler for this event, it instead goes to the defined
[uncaught exception][uncaughtException] handler. The default behavior of the
uncaught exception handler is documented:

> By default, Node.js handles such exceptions by printing the stack trace to
> stderr and exiting.
## Handling the Errors

Since allowing the errors to make it to the uncaught exception handler isn’t
useful, we should handle the exceptions properly. Let’s give that a quick shot.

```javascript
var gulp = require('gulp');
var uglify = require('gulp-uglify');

gulp.task('compress', function () {
return gulp.src('lib/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist'))
.on('error', function(err) {
console.error('Error in compress task', err.toString());
});
});
```

Unfortunately, Node.js stream’s `pipe` function doesn’t forward errors through
the chain, so this error handler only handles the errors given by
`gulp.dest`. Instead we need to handle errors for each stream.

```javascript
var gulp = require('gulp');
var uglify = require('gulp-uglify');

gulp.task('compress', function () {
function createErrorHandler(name) {
return function (err) {
console.error('Error from ' + name + ' in compress task', err.toString());
};
}

return gulp.src('lib/*.js')
.on('error', createErrorHandler('gulp.src'))
.pipe(uglify())
.on('error', createErrorHandler('uglify'))
.pipe(gulp.dest('dist'))
.on('error', createErrorHandler('gulp.dest'));
});
```

This is a lot of complexity to add in each of your gulp tasks, and it’s easy to
forget to do it. In addition, it’s still not perfect, as it doesn’t properly
signal to gulp’s task system that the task has failed. We can fix this, and we
can handle the other pesky issues with error propogations with streams, but it’s
even more work!

## Using pump

The [`pump`][pump] module is a cheat code of sorts. It’s a wrapper around the
`pipe` functionality that handles these cases for you, so you can stop hacking
on your gulpfiles, and get back to hacking new features into your app.

```javascript
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var pump = require('pump');

gulp.task('compress', function (cb) {
pump([
gulp.src('lib/*.js'),
uglify(),
gulp.dest('dist')
],
cb
);
});
```

The gulp task system provides a gulp task with a callback, which can signal
successful task completion (being called with no arguments), or a task failure
(being called with an Error argument). Fortunately, this is the exact same
format `pump` uses!

![pump error](pump-error.png)

Now it’s very clear what plugin the error was from, what the error actually was,
and from what file and line number.

[pump]: https://github.com/mafintosh/pump
[uncaughtException]: https://nodejs.org/api/process.html#process_event_uncaughtexception
Binary file added docs/why-use-pump/pipe-error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/why-use-pump/pump-error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 45adfc3

Please sign in to comment.