https://github.com/kumavis/iframe-stream/blob/master/test/rebundle.js
iframe-stream-其实就是将iframe打包成流
Create a stream around an iframe via post-message-stream
const IframeStream = require('iframe-stream').IframeStream var iframe = createIframe() var iframeStream = IframeStream(iframe)
Note
- Setup the stream immediately, so we don't miss the iframe's
load
event. - The IframeStream will buffer all input until the childstream is ready.
- This is an object stream, and buffers will not be handled gracefully.
Example
Here is an example using dnode to create a callback based API with a javascript context inside an iframe.
Parent:
const IframeStream = require('iframe-stream').IframeStream const Dnode = require('dnode') var iframe = createIframe() var iframeStream = IframeStream(iframe) var dnode = Dnode() dnode.on('remote', function(child){ child.doAsyncSomething(function(){ console.log('child finished doing the thing!') }) }) dnode.pipe(iframeStream).pipe(dnode)
Child:
const ParentStream = require('iframe-stream').ParentStream const Dnode = require('dnode') var parentStream = ParentStream(iframe) var dnode = Dnode({ doAsyncSomething: function (cb) { console.log('doing something async...') cb() } }) dnode.pipe(parentStream).pipe(dnode)
var PostMessageStream = require('post-message-stream') /* IframeStream starts corked until it gets a message from the iframe ParentStream starts uncorked */ module.exports = { IframeStream: IframeStream, ParentStream: ParentStream, } function IframeStream(iframe) { if (this instanceof IframeStream) throw Error('IframeStream - Dont construct via the "new" keyword.') return new PostMessageStream({ name: 'iframe-parent', target: 'iframe-child', targetWindow: iframe.contentWindow, }) } // // Parent Stream // function ParentStream() { if (this instanceof ParentStream) throw Error('ParentStream - Dont construct via the "new" keyword.') return new PostMessageStream({ name: 'iframe-child', target: 'iframe-parent', targetWindow: frames.parent, }) }
npm install iframe --save npm install iframe-stream --save npm install dnode --save
index.js
const test = require('tape') const Iframe = require('iframe') const from = require('from') const pipe = require('mississippi').pipe const IframeStream = require('../').IframeStream const rebundle = require('./rebundle') const htmlWrap = require('./htmlWrap') const iframeContent = htmlWrap(rebundle(require('./frame'))) // setup iframe var iframe = Iframe({ body: iframeContent, container: document.body, }).iframe var iframeStream = IframeStream(iframe) test(function(t) { var data = [1, 2, 3, 4, 50, 1000, 256, 19, 12] t.plan(data.length) pipe( from(data), iframeStream ) // create a test for each datum // this is because these streams never close eachOutput(iframeStream, data.map(function(datum){ return function onResult(result){ t.equal(result, datum * 2, 'datum was doubled correctly') } }), function onDone(){ t.end() }) }) function eachOutput(stream, handlers, cb) { var index = 0 if (!handlers.length) return cb() stream.once('data', handleChunk) function handleChunk(data){ var fn = handlers[index] fn(data) index++ if (!handlers[index]) return cb() stream.once('data', handleChunk) } }
htmlWrap.js
module.exports = htmlWrap function htmlWrap(src){ return '<'+'script type="text/javascript"'+'>'+src+'<'+'/script'+'>' }
rebundle.js
// // Extraced from WebWorkify // https://github.com/substack/webworkify/blob/master/index.js // var bundleFn = arguments[3]; var sources = arguments[4]; var cache = arguments[5]; var stringify = JSON.stringify; module.exports = function (fn, options) { var wkey; var cacheKeys = Object.keys(cache); for (var i = 0, l = cacheKeys.length; i < l; i++) { var key = cacheKeys[i]; var exp = cache[key].exports; // Using babel as a transpiler to use esmodule, the export will always // be an object with the default export as a property of it. To ensure // the existing api and babel esmodule exports are both supported we // check for both if (exp === fn || exp && exp.default === fn) { wkey = key; break; } } if (!wkey) { wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); var wcache = {}; for (var i = 0, l = cacheKeys.length; i < l; i++) { var key = cacheKeys[i]; wcache[key] = key; } sources[wkey] = [ Function(['require','module','exports'], '(' + fn + ')(self)'), wcache ]; } var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); var scache = {}; scache[wkey] = wkey; sources[skey] = [ Function(['require'], ( // try to call default if defined to also support babel esmodule // exports 'var f = require(' + stringify(wkey) + ');' + '(f.default ? f.default : f)(self);' )), scache ]; var workerSources = {}; resolveSources(skey); function resolveSources(key) { workerSources[key] = true; for (var depPath in sources[key][1]) { var depKey = sources[key][1][depPath]; if (!workerSources[depKey]) { resolveSources(depKey); } } } var src = '(' + bundleFn + ')({' + Object.keys(workerSources).map(function (key) { return stringify(key) + ':[' + sources[key][0] + ',' + stringify(sources[key][1]) + ']' ; }).join(',') + '},{},[' + stringify(skey) + '])' ; return src }
frame.js
const BrowserStdout = require('browser-stdout') const ParentStream = require('../index.js').ParentStream const transform = require('mississippi').through const pipe = require('mississippi').pipe module.exports = setupStream setupStream() function setupStream(opts) { var iframeStream = ParentStream() pipe( iframeStream, transform({ objectMode: true }, doubleIt), iframeStream ) } function doubleIt(chunk, encoding, cb){ cb(null, chunk * 2) }
上面的例子是iframe-stream作者写的一个测试test