Closed kristianmandrup closed 7 years ago
It should be! Please let me know if it doesn't.
Just thought I'd stop by and share some observations I've made in trying to integrate spdy
into koa@2
.
First, I generate a manifest of assets to be pushed to the client using http2-push-manifest.
{
"/static/main-9a42a4188a.css": {
"weight": 1,
"type": "style"
},
"/app/common_2-3574809b05.js": {
"weight": 1,
"type": "script"
},
"/static/js/primus.js": {
"weight": 1,
"type": "script"
},
"/bower_components/polymer/polymer.html": {
"weight": 1,
"type": "document"
}
}
Now, tack on a couple o' more assets in there (we've got a total of 150 in this manifest).
Then we move into the koa
part where we have a middleware that sets up a Link
header containing multiple 'push instructions'(?).
function manifestMw (opts) {
const manifest = require(path.resolve('.', opts.manifest));
return function (ctx, next) {
// If we receive a request for a file _inside_ the manifest, move on to the next middleware.
if (manifest[ctx.req.url]) {
return next();
}
const links = [];
Object.keys(manifest).forEach(key => {
const u = url.resolve(`${ctx.protocol}://${ctx.host}`, key);
const link = `<${u}>; rel=preload; as=${manifest[key].type}`;
links.push(link);
});
ctx.set('Link', links.join(', '));
// Link: <https://localhost:3000/static/main-9a42a4188a.css>; rel=preload; as=style, <https://localhost:3000/app/common_2-3574809b05.js>; rel=preload; as=script, <https://localhost:3000/static/js/primus.js>; rel=preload; as=script, <https://localhost:3000/bower_components/polymer/polymer.html>; rel=preload; as=document
ctx.state.h2 = manifest;
/**
* ctx.state.h2 =
* { '/static/main-9a42a4188a.css': { weight: 1, type: 'style' },
* '/app/common_2-3574809b05.js': { weight: 1, type: 'script' },
* '/static/js/primus.js': { weight: 1, type: 'script' },
* '/bower_components/polymer/polymer.html': { weight: 1, type: 'document' } } }
*/
return next();
}
}
koa.use(manifestMw('push_manifest.json'));
Then we move on to the next middleware that starts pushing things out to the client:
function pusher () {
return function (ctx, next) {
function push (file) {
const opts = {
request: {
accept: '*/*'
},
response: {
'content-type': mime.lookup(file)
}
};
const p = ctx.res.push(file, opts, (_, stream) => {
// cleanup function borrowed from spdy-push
function cleanup (err) {
if (err) {
console.error(chalk.red(err.stack));
}
stream.removeListener('error', cleanup);
stream.removeListener('close', cleanup);
stream.removeListener('finish', cleanup);
destroy(content);
}
stream.on('error', cleanup);
stream.on('close', cleanup);
stream.on('finish', cleanup);
});
const content = fs.createReadStream(process.cwd() + '/dist' + file);
content.pipe(p);
}
if (ctx.req.url === '/') {
Object.keys(ctx.state.h2.manifest).map(push);
}
return next();
}
}
koa.use(pusher());
And the server itself:
// construct the koa app with env & CLI flags
const koa = buildKoa(env, flags);
const spdyConf = {
key: fs.readFileSync(`${__dirname}/f.dev.key`),
cert: fs.readFileSync(`${__dirname}/f.dev.crt`)
};
const server = spdy.createServer(spdyConf, koa.callback());
I'm quite new to SPDY Push Streams and how I should be incorporating them into Koa, this is/was my best guess after looking at similar projects that didn't work "out of the box".
I'm quite certain there's a bug or two in here that's causing the following issues that start pouring in on the initial index request: Got RST: PROTOCOL_ERROR
's in my cleanup
handler.
Stack trace looks as such:
at Stream._handleRST (/Users/kasperlewau/code/falcon/html2/node_modules/spdy-transport/lib/spdy-transport/stream.js:280:24)
at Stream._handleFrame (/Users/kasperlewau/code/falcon/html2/node_modules/spdy-transport/lib/spdy-transport/stream.js:126:10)
at Connection._handleFrame (/Users/kasperlewau/code/falcon/html2/node_modules/spdy-transport/lib/spdy-transport/connection.js:329:12)
at Parser.<anonymous> (/Users/kasperlewau/code/falcon/html2/node_modules/spdy-transport/lib/spdy-transport/connection.js:161:10)
at emitOne (events.js:96:13)
at Parser.emit (events.js:188:7)
at readableAddChunk (/Users/kasperlewau/code/falcon/html2/node_modules/readable-stream/lib/_stream_readable.js:213:18)
at Parser.Readable.push (/Users/kasperlewau/code/falcon/html2/node_modules/readable-stream/lib/_stream_readable.js:172:10)
at Parser.Transform.push (/Users/kasperlewau/code/falcon/html2/node_modules/readable-stream/lib/_stream_transform.js:123:32)
at next (/Users/kasperlewau/code/falcon/html2/node_modules/spdy-transport/lib/spdy-transport/protocol/base/parser.js:52:12)
packages & versions used;
"koa": "^2.0.0-alpha.5",
"spdy": "^3.4.0"
I followed the code and I got as far as the FLOW_CONTROL_ERROR
at _onWindowOverflow
- and now my brain is toast. 😆 I'll get back to cleaning the apartment for a couple o' hours and see if I can get any further with this.
Is spdy compatible with Koa (express for ES6/7) or what would be required for this to work.