From c86968f0024db1e194d38777a568b0088928b74a Mon Sep 17 00:00:00 2001 From: John Gozde Date: Sat, 16 Aug 2014 02:03:11 -0600 Subject: [PATCH 1/2] Add support for multiple bundle() calls. - works in watchify - re-adds pipeline hooks on 'reset' - add opts.outputs alias for opts.o + docs --- index.js | 81 +++++++++++++++++++++++++++---------------------- readme.markdown | 5 ++- test/plugin.js | 33 ++++++++++++++++++++ 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/index.js b/index.js index e0c7b13..4eb4c22 100644 --- a/index.js +++ b/index.js @@ -24,47 +24,54 @@ module.exports = function f (b, opts) { var needRecords = !files.length; + opts.outputs = opts.outputs || opts.o; opts.objectMode = true; opts.raw = true; opts.rmap = {}; - b.pipeline.get('record').push(through.obj(function(row, enc, next) { - if (needRecords) { - files.push(row.file); - } - next(null, row); - }, function(next) { - var cwd = defined(opts.basedir, b._options.basedir, process.cwd()); - var fileMap = files.reduce(function (acc, x, ix) { - acc[path.resolve(cwd, x)] = opts.o[ix]; - return acc; - }, {}); - - // Force browser-pack to wrap the common bundle - b._bpack.hasExports = true; - var packOpts = xtend(b._options, { - raw: true, - hasExports: true - }); - - var s = createStream(files, opts); - s.on('stream', function (bundle) { - var output = fileMap[bundle.file]; - var ws = isStream(output) ? output : fs.createWriteStream(output); - - bundle.pipe(pack(packOpts)).pipe(ws); - }); - - b.pipeline.get('pack').unshift(s); - - next(); - })); - - - b.pipeline.get('label').push(through.obj(function(row, enc, next) { - opts.rmap[row.id] = row.file; - next(null, row); - })); + b.on('reset', addHooks); + addHooks(); + + function addHooks() { + b.pipeline.get('record').push(through.obj(function(row, enc, next) { + if (needRecords) { + files.push(row.file); + } + next(null, row); + }, function(next) { + var cwd = defined(opts.basedir, b._options.basedir, process.cwd()); + var fileMap = files.reduce(function (acc, x, ix) { + acc[path.resolve(cwd, x)] = opts.outputs[ix]; + return acc; + }, {}); + + // Force browser-pack to wrap the common bundle + b._bpack.hasExports = true; + var packOpts = xtend(b._options, { + raw: true, + hasExports: true + }); + + var s = createStream(files, opts); + s.on('stream', function (bundle) { + var output = fileMap[bundle.file]; + var ws = isStream(output) ? output : fs.createWriteStream(output); + + bundle.pipe(pack(packOpts)).pipe(ws); + }); + + b.pipeline.get('pack').unshift(s); + + if (needRecords) files = []; + + next(); + })); + + b.pipeline.get('label').push(through.obj(function(row, enc, next) { + opts.rmap[row.id] = row.file; + next(null, row); + })); + } return b; diff --git a/readme.markdown b/readme.markdown index b9af48c..b8cbc4a 100644 --- a/readme.markdown +++ b/readme.markdown @@ -129,10 +129,13 @@ The output format for `fr` and each of the `fr` sub-streams given by each `'stream'` event is also in the [module-deps](https://npmjs.org/package/module-deps) format. -`opts.o` should be an array that pairs up with the `files` array to specify +`opts.o` or `opts.outputs` should be an array that pairs up with the `files` array to specify where each bundle output for each entry file should be written. The elements in `opts.o` can be string filenames or writable streams. +`opts.entries` or `opts.e` is an optional array of entries that may be used +instead of passing entries to browserify. + The files held in common among `> opts.threshold` (default: 1) bundles will be output on the `fr` stream itself. The entry-specific bundles are diverted into each `'stream'` event's output. `opts.threshold` can be a number or a function diff --git a/test/plugin.js b/test/plugin.js index d87a2c2..aa37d2a 100644 --- a/test/plugin.js +++ b/test/plugin.js @@ -66,3 +66,36 @@ test('browserify plugin streams', function(t) { } } }); })); }); + +test('browserify plugin multiple bundle calls', function(t) { + t.plan(4); + + var b = browserify(files); + var sources = {}; + b.plugin(factor, { + o: [ + function() { return concat(function(data) { sources.x = data }); }, + function() { return concat(function(data) { sources.y = data }); } + ] + }); + + b.bundle().pipe(concat(function(data) { + checkBundle(data); + + b.bundle().pipe(concat(checkBundle)); + })); + + function checkBundle(data) { + var common = data.toString('utf8'); + var x = sources.x.toString('utf8'); + var y = sources.y.toString('utf8'); + + vm.runInNewContext(common + x, { console: { log: function (msg) { + t.equal(msg, 55500); + } } }); + + vm.runInNewContext(common + y, { console: { log: function (msg) { + t.equal(msg, 333); + } } }); + } +}); From bec04df0d4c04b6eddcffec38e600c396ae9b3e2 Mon Sep 17 00:00:00 2001 From: John Gozde Date: Sat, 6 Sep 2014 11:33:31 -0600 Subject: [PATCH 2/2] Expose pipeline for output bundles on event. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - browserify instance emits ‘factor.pipeline’ event when the pipeline is created - pipeline uses labeled-stream-splicer and has ‘pack’ and ‘wrap’ stages --- index.js | 34 +++++++++++++++++++++++----------- package.json | 1 + readme.markdown | 11 +++++++++++ test/plugin.js | 11 ++++++----- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/index.js b/index.js index 4eb4c22..4462787 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,7 @@ var fs = require('fs'); var pack = require('browser-pack'); var xtend = require('xtend'); var defined = require('defined'); +var splicer = require('labeled-stream-splicer'); module.exports = function f (b, opts) { if (!opts) opts = {}; @@ -24,15 +25,20 @@ module.exports = function f (b, opts) { var needRecords = !files.length; - opts.outputs = opts.outputs || opts.o; + opts.outputs = defined(opts.outputs, opts.o, {}); opts.objectMode = true; opts.raw = true; opts.rmap = {}; + var packOpts = xtend(b._options, { + raw: true, + hasExports: true + }); + b.on('reset', addHooks); addHooks(); - function addHooks() { + function addHooks () { b.pipeline.get('record').push(through.obj(function(row, enc, next) { if (needRecords) { files.push(row.file); @@ -40,24 +46,30 @@ module.exports = function f (b, opts) { next(null, row); }, function(next) { var cwd = defined(opts.basedir, b._options.basedir, process.cwd()); - var fileMap = files.reduce(function (acc, x, ix) { - acc[path.resolve(cwd, x)] = opts.outputs[ix]; + var pipelines = files.reduce(function (acc, x, ix) { + var pipeline = splicer.obj([ + 'pack', [ pack(packOpts) ], + 'wrap', [] + ]); + var output = opts.outputs[ix]; + if (output) { + var ws = isStream(output) ? output : fs.createWriteStream(output); + pipeline.push(ws); + } + acc[path.resolve(cwd, x)] = pipeline; return acc; }, {}); // Force browser-pack to wrap the common bundle b._bpack.hasExports = true; - var packOpts = xtend(b._options, { - raw: true, - hasExports: true + + Object.keys(pipelines).forEach(function (id) { + b.emit('factor.pipeline', id, pipelines[id]); }); var s = createStream(files, opts); s.on('stream', function (bundle) { - var output = fileMap[bundle.file]; - var ws = isStream(output) ? output : fs.createWriteStream(output); - - bundle.pipe(pack(packOpts)).pipe(ws); + bundle.pipe(pipelines[bundle.file]); }); b.pipeline.get('pack').unshift(s); diff --git a/package.json b/package.json index 90eca35..b906101 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "defined": "0.0.0", "deps-topo-sort": "~0.2.1", "inherits": "^2.0.1", + "labeled-stream-splicer": "^1.0.0", "minimist": "~0.2.0", "nub": "0.0.0", "reversepoint": "~0.2.0", diff --git a/readme.markdown b/readme.markdown index b8cbc4a..cf3a61d 100644 --- a/readme.markdown +++ b/readme.markdown @@ -164,6 +164,17 @@ default). The entry file name is available as `stream.file`. +## b.on('factor.pipeline', function (file, pipeline) {}) + +Emits the full path to the entry file (`file`) and a [labeled-stream-splicer](https://npmjs.org/package/labeled-stream-splicer) (`pipeline`) for each entry file with these labels: + +* `'pack'` - [browser-pack](https://npmjs.org/package/browser-pack) +* `'wrap'` - apply final wrapping + +You can call `pipeline.get` with a label name to get a handle on a stream pipeline that you can `push()`, `unshift()`, or `splice()` to insert your own transform streams. + +Event handlers must be attached *before* calling `b.plugin`. + # install With [npm](https://npmjs.org) do: diff --git a/test/plugin.js b/test/plugin.js index aa37d2a..0f99edd 100644 --- a/test/plugin.js +++ b/test/plugin.js @@ -72,12 +72,13 @@ test('browserify plugin multiple bundle calls', function(t) { var b = browserify(files); var sources = {}; - b.plugin(factor, { - o: [ - function() { return concat(function(data) { sources.x = data }); }, - function() { return concat(function(data) { sources.y = data }); } - ] + b.on('factor.pipeline', function(id, pipeline) { + pipeline.pipe(concat(function(data) { + if (/x\.js$/.test(id)) sources.x = data; + else sources.y = data; + })); }); + b.plugin(factor); b.bundle().pipe(concat(function(data) { checkBundle(data);