Skip to content

Commit

Permalink
fix stream error handling for bundling and watching. Fixes #43 and #31
Browse files Browse the repository at this point in the history
  • Loading branch information
chmontgomery committed Mar 1, 2015
1 parent aaee626 commit d0cd319
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 29 deletions.
9 changes: 9 additions & 0 deletions examples/6to5/gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var gulp = require('gulp'),
rimraf = require('gulp-rimraf'),
path = require('path'),
bundle = require('../../');

gulp.task('bundle', ['clean'], function () {
Expand All @@ -11,4 +12,12 @@ gulp.task('bundle', ['clean'], function () {
gulp.task('clean', function () {
return gulp.src('./public', { read: false })
.pipe(rimraf());
});

// rebuild bundle on change of a source file
gulp.task('watch', function () {
bundle.watch({
configPath: path.join(__dirname, 'bundle.config.js'),
dest: path.join(__dirname, 'public')
});
});
12 changes: 11 additions & 1 deletion examples/browserify/bundle.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var transformHelper = require('../../index.js').transformHelper,
browserify = require('browserify'),
sourceStream = require('vinyl-source-stream'),
isDebug = (process.env.NODE_ENV !== 'production');
isDebug = (process.env.NODE_ENV !== 'production'),
gutil = require('gulp-util');

var mainStream = function (file, done) {
browserify({
Expand All @@ -16,6 +17,15 @@ var mainStream = function (file, done) {
//.transform(reactify)
//.require(vendorLibs)
.bundle()
.on('error', function (err) {
// make sure browserify errors don't break the pipe during watch
if (file.bundleOptions.isWatch) {
gutil.log(gutil.colors.red(err.toString()));
this.emit('end');
} else {
throw err;
}
})
.pipe(sourceStream('app.js')) // convert to gulp stream
.pipe(done); // make sure to pipe to the "done" stream
};
Expand Down
1 change: 1 addition & 0 deletions examples/browserify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"devDependencies": {
"browserify": "^8.1.3",
"gulp": "^3.8.10",
"gulp-util": "^3.0.4",
"gulp-rimraf": "^0.1.1",
"vinyl-source-stream": "^1.0.0"
}
Expand Down
4 changes: 3 additions & 1 deletion examples/custom-transforms/bundle.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ module.exports = {
],
styles: [
'./content/**/*.scss',
'./content/**/*.less'
'./content/**/*.less',
'./content/**/*.css'
],
options: {
minCSS: true,
transforms: {
scripts: scriptTransforms,
styles: styleTransforms
Expand Down
2 changes: 1 addition & 1 deletion examples/custom-transforms/bundle.result.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"article": {
"scripts": "<script src='/public/article-0e717735.js' type='text/javascript'></script>",
"styles": "<link href='/public/article-05a1266f.css' media='all' rel='stylesheet' type='text/css'/>"
"styles": "<link href='/public/article-950e9844.css' media='all' rel='stylesheet' type='text/css'/>"
}
}
3 changes: 3 additions & 0 deletions examples/custom-transforms/content/styles/regular.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.my-regular-css {
background-color: blue;
}
11 changes: 9 additions & 2 deletions examples/custom-transforms/gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
var gulp = require('gulp'),
rimraf = require('gulp-rimraf'),
path = require('path'),
bundle = require('../../index');

gulp.task('bundle', ['clean'], function () {

return gulp.src('./bundle.config.js')
.pipe(bundle())
.pipe(bundle.results({
Expand All @@ -14,6 +14,13 @@ gulp.task('bundle', ['clean'], function () {
});

gulp.task('clean', function () {
return gulp.src('./public', { read: false })
return gulp.src('./public', {read: false})
.pipe(rimraf());
});

gulp.task('watch', function () {
bundle.watch({
configPath: path.join(__dirname, 'bundle.config.js'),
dest: path.join(__dirname, 'public')
});
});

Large diffs are not rendered by default.

This file was deleted.

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions examples/custom-transforms/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ NOTE: any plugin you wish to use should support [sourcemaps](https://github.com/
otherwise it will break the resulting sourcemaps generation.
See [here on how to add this support to a gulp plugin](https://github.com/floridoo/gulp-sourcemaps#plugin-developers-only-how-to-add-source-map-support-to-plugins).

NOTE 2: By default, the bundler will detect whether you're doing a typical build or running in watch mode. If it's the
later, the bundler will simply log the error and not stop the stream. That said, browserify works slightly differently
and you'll need to handle those errors manually. [See the browserify example for how to do this](../browserify).

## How to define custom transforms

Define your custom transforms as part of a [`lazypipe`](https://github.com/OverZealous/lazypipe) stream.
Expand Down
4 changes: 2 additions & 2 deletions examples/result-json/bundle.result.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": "<script src='/public/main-2742a3c0.js' type='text/javascript'></script>"
},
"vendor": {
"scripts": "<script src='/public/vendor-6873f46e.js' type='text/javascript'></script>",
"styles": "<link href='/public/vendor-7c38ff67.css' media='all' rel='stylesheet' type='text/css'/>"
"styles": "<link href='/public/vendor-7c38ff67.css' media='all' rel='stylesheet' type='text/css'/>",
"scripts": "<script src='/public/vendor-6873f46e.js' type='text/javascript'></script>"
}
}
6 changes: 4 additions & 2 deletions lib/stream-bundles-watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ function _bundle(config, env) {
bundleName: bundleName,
bundleOptions: namedBundleObj[BundleKeys.OPTIONS],
isBundleAll: isBundleAll,
minSrcs: minSrcs
minSrcs: minSrcs,
isWatch: true
})
.pipe(gif(resultOpts, results(resultOpts)))
.pipe(gulp.dest(config.options.dest))
Expand Down Expand Up @@ -102,7 +103,8 @@ function _bundle(config, env) {
bundleName: bundleName,
bundleOptions: namedBundleObj[BundleKeys.OPTIONS],
isBundleAll: isBundleAll,
minSrcs: minSrcs
minSrcs: minSrcs,
isWatch: true
})
.pipe(gif(resultOpts, results(resultOpts)))
.pipe(gulp.dest(config.options.dest))
Expand Down
37 changes: 33 additions & 4 deletions lib/stream-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,43 @@ var gulp = require('gulp'),
BundleKeys = require('./model/bundle-keys'),
isMinEnabled = require('./is-min-enabled');

module.exports.handleTransformError = function (bundleName, bundleKey, err) {
module.exports.handleTransformError = function (thisStream, isWatch, bundleName, bundleKey, err) {
logger.log(gutil.colors.red("ERROR in custom transforms for '" + bundleName + "." + bundleKey + "':"));
logger.log(err);
logger.log(err.toString());
if (isWatch) {
thisStream.emit('end');
} else {
process.exit(1);
}
};

module.exports.attachStreamOptions = function (file, opts) {
// add some useful options to file for possible inspection later in external custom gulp streams
file.bundleOptions = {
env: opts.env,
type: opts.type,
bundleName: opts.bundleName,
isWatch: opts.isWatch,
isBundleAll: opts.isBundleAll
};
};

module.exports.scripts = function (opts) {
var self = this;
return gulp.src(opts.src, {base: opts.base})
.pipe(using.bundle(opts.bundleName, BundleKeys.SCRIPTS, opts.env, opts.isBundleAll))
.pipe(through.obj(function (file, enc, cb) {
self.attachStreamOptions(file, opts);
this.push(file);
cb();
}))
.pipe(gif(function (file) {
return sourcemaps.isEnabled(opts);
}, gsourcemaps.init({loadMaps: true})
))
.pipe(opts.bundleOptions.transforms[BundleKeys.SCRIPTS]())
.on('error', function (e) {
self.handleTransformError(opts.bundleName, BundleKeys.SCRIPTS, e);
self.handleTransformError(this, opts.isWatch, opts.bundleName, BundleKeys.SCRIPTS, e);
})
.pipe(gif(function (file) {
return sourcemaps.isEnabled(opts);
Expand All @@ -47,6 +68,9 @@ module.exports.scripts = function (opts) {
uglify()),
uglify()
)))
.on('error', function (e) {
self.handleTransformError(this, opts.isWatch, opts.bundleName, BundleKeys.SCRIPTS, e);
})
.pipe(gif(function (file) {
return file.isStream();
},
Expand All @@ -69,14 +93,19 @@ module.exports.styles = function (opts) {
var self = this;
return gulp.src(opts.src, {base: opts.base})
.pipe(using.bundle(opts.bundleName, BundleKeys.STYLES, opts.env, opts.isBundleAll))
.pipe(through.obj(function (file, enc, cb) {
self.attachStreamOptions(file, opts);
this.push(file);
cb();
}))
.pipe(
gif(function (file) {
return sourcemaps.isEnabled(opts);
}, gsourcemaps.init({loadMaps: true})
))
.pipe(opts.bundleOptions.transforms[BundleKeys.STYLES]())
.on('error', function (e) {
self.handleTransformError(opts.bundleName, BundleKeys.STYLES, e);
self.handleTransformError(this, opts.isWatch, opts.bundleName, BundleKeys.STYLES, e);
})
.pipe(gif(function (file) {
return sourcemaps.isEnabled(opts);
Expand Down
83 changes: 69 additions & 14 deletions test/unit/stream-files-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ describe('stream-files', function () {
describe('styles', function () {

it('should call error handler when custom transform fails', function (done) {
streamFiles.handleTransformError = function (bundleName, bundleKey, err) {
streamFiles.handleTransformError = function (thisStream, isWatch, bundleName, bundleKey, err) {
should.not.exist(isWatch);
should.exist(thisStream);
bundleName.should.eql('main');
bundleKey.should.eql('styles');
//should(err).typeof('object');
Expand Down Expand Up @@ -43,7 +45,9 @@ describe('stream-files', function () {
describe('scripts', function () {

it('should call error handler when custom transform fails', function (done) {
streamFiles.handleTransformError = function (bundleName, bundleKey, err) {
streamFiles.handleTransformError = function (thisStream, isWatch, bundleName, bundleKey, err) {
should.not.exist(isWatch);
should.exist(thisStream);
bundleName.should.eql('main');
bundleKey.should.eql('scripts');
//should(err).typeof('object');
Expand All @@ -70,23 +74,74 @@ describe('stream-files', function () {

});


describe('handleTransformError', function () {

var mockLogger = {
log: function () {
}
};
var spy = sinon.spy(mockLogger, 'log');
var streamFiles = proxyquire(libPath + '/stream-files', {
'./service/logger': mockLogger
it('should log errors during watch', function () {
var mockLogger = {
log: function () {
}
};
var mockPipe = {
emit: function () {
}
};
var logSpy = sinon.spy(mockLogger, 'log');
var pipeSpy = sinon.spy(mockPipe, 'emit');
var streamFiles = proxyquire(libPath + '/stream-files', {
'./service/logger': mockLogger
});
var errObj = new Error('my err');
streamFiles.handleTransformError(mockPipe, true, 'my_bundle_name', 'my_bundle_key', errObj);
logSpy.calledTwice.should.be.ok;
pipeSpy.calledOnce.should.be.ok;
pipeSpy.withArgs('end').calledOnce.should.be.ok;
});

it('should log errors', function () {
it('should process.exit when errors during bundle', function () {
var mockProcessExit = sinon.spy(),
origExit = process.exit;
process.exit = mockProcessExit;

var mockLogger = {
log: function () {
}
};
var logSpy = sinon.spy(mockLogger, 'log');
var streamFiles = proxyquire(libPath + '/stream-files', {
'./service/logger': mockLogger
});
var errObj = new Error('my err');
streamFiles.handleTransformError('my_bundle_name', 'my_bundle_key', errObj);
spy.calledTwice.should.be.ok;
spy.withArgs(errObj).calledOnce.should.be.ok;
streamFiles.handleTransformError(null, undefined, 'my_bundle_name', 'my_bundle_key', errObj);
logSpy.calledTwice.should.be.ok;
mockProcessExit.calledOnce.should.be.ok;

process.exit = origExit;
});

});

describe('attachStreamOptions', function () {

var streamFiles = require(libPath + '/stream-files');

it('should attach specific options to file obj', function () {

var fakeFile = {};
streamFiles.attachStreamOptions(fakeFile, {
env: 'production',
type: 'scripts',
bundleName: 'my_bundle_name',
isWatch: true,
isBundleAll: false
});

fakeFile.bundleOptions.should.be.ok;
fakeFile.bundleOptions.env.should.eql('production');
fakeFile.bundleOptions.type.should.eql('scripts');
fakeFile.bundleOptions.bundleName.should.eql('my_bundle_name');
fakeFile.bundleOptions.isWatch.should.be.ok;
fakeFile.bundleOptions.isBundleAll.should.not.be.ok;

});

});
Expand Down

0 comments on commit d0cd319

Please sign in to comment.