diff --git a/lib/index.js b/lib/index.js index 5279ff3..326a298 100644 --- a/lib/index.js +++ b/lib/index.js @@ -23,9 +23,11 @@ function connect_dev() { heartbeat: 10 * 1000 }), - async (req, res, next) => { - asset_cache = await watcher.ready; - next(); + (req, res, next) => { + watcher.ready.then(cache => { + asset_cache = cache; + next(); + }); }, set_req_pathname, @@ -126,7 +128,7 @@ function get_asset_handler(opts) { } function get_route_handler(fn) { - return async function handle_route(req, res, next) { + return function handle_route(req, res, next) { const url = req.pathname; const { client, server } = fn(); @@ -136,57 +138,66 @@ function get_route_handler(fn) { 'Content-Type': 'text/html' }); - try { - for (const route of route_manager.routes) { - if (route.test(url)) { - req.params = route.exec(url); - - const mod = require(server.entry)[route.id]; - - if (route.type === 'page') { - // preload main.js and current route - // TODO detect other stuff we can preload? images, CSS, fonts? - res.set('Link', `<${client.main_file}>;rel="preload";as="script", <${client.routes[route.id]}>;rel="preload";as="script"`); - - const data = { params: req.params, query: req.query }; - - if (mod.preload) { - const promise = Promise.resolve(mod.preload(req)).then(preloaded => { - Object.assign(data, preloaded); - return mod.render(data); - }); - - await templates.stream(res, 200, { - main: client.main_file, - html: promise.then(rendered => rendered.html), - head: promise.then(({ head }) => `${head}`), - styles: promise.then(({ css }) => (css && css.code ? `` : '')) - }); - } else { - const { html, head, css } = mod.render(data); - - const page = templates.render(200, { - main: client.main_file, - html, - head: `${head}`, - styles: (css && css.code ? `` : '') - }); - - res.end(page); - } - } - - else { - const handler = mod[req.method.toLowerCase()]; - if (handler) handler(req, res, next); - } - - return; - } + let i = 0; + function handle_route_inner() { + if (i === route_manager.routes.length) { + next(); + return; } - next(); - } catch(err) { + const route = route_manager.routes[i]; + + if (route.test(url)) { + req.params = route.exec(url); + + const mod = require(server.entry)[route.id]; + + if (route.type === 'page') { + // preload main.js and current route + // TODO detect other stuff we can preload? images, CSS, fonts? + res.set('Link', `<${client.main_file}>;rel="preload";as="script", <${client.routes[route.id]}>;rel="preload";as="script"`); + + const data = { params: req.params, query: req.query }; + + if (mod.preload) { + const promise = Promise.resolve(mod.preload(req)).then(preloaded => { + Object.assign(data, preloaded); + return mod.render(data); + }); + + return templates.stream(res, 200, { + main: client.main_file, + html: promise.then(rendered => rendered.html), + head: promise.then(({ head }) => `${head}`), + styles: promise.then(({ css }) => (css && css.code ? `` : '')) + }); + } else { + const { html, head, css } = mod.render(data); + + const page = templates.render(200, { + main: client.main_file, + html, + head: `${head}`, + styles: (css && css.code ? `` : '') + }); + + res.end(page); + } + } + + else { + const handler = mod[req.method.toLowerCase()]; + if (handler) handler(req, res, next); + } + + return; + } + + ++i; + return handle_route_inner(); + } + + return Promise.resolve().then(handle_route_inner).catch(err => { res.status(500); res.end(templates.render(500, { title: (err && err.name) || 'Internal server error', @@ -194,7 +205,7 @@ function get_route_handler(fn) { error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), stack: err && err.stack.split('\n').slice(1).join('\n') })); - } + }); }; } diff --git a/lib/templates.js b/lib/templates.js index 34360d1..8260aa8 100644 --- a/lib/templates.js +++ b/lib/templates.js @@ -31,10 +31,14 @@ function create_templates() { return key in data ? data[key] : ''; }); }, - stream: async (res, data) => { + stream: (res, data) => { let i = 0; - do { + function stream_inner() { + if (i >= template.length) { + return; + } + const start = template.indexOf('%sapper', i); if (start === -1) { @@ -53,9 +57,14 @@ function create_templates() { const match = /sapper\.(\w+)/.exec(tag); if (!match || !(match[1] in data)) throw new Error(`Bad template`); // TODO ditto - res.write(await data[match[1]]); - i = end + 1; - } while (i < template.length); + return Promise.resolve(data[match[1]]).then(datamatch => { + res.write(datamatch); + i = end + 1; + return stream_inner(); + }); + } + + return Promise.resolve().then(stream_inner); } }; })