From 99853c51811d5aff780d7df2e16c94b5124b6d75 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 3 Mar 2018 21:48:50 -0500 Subject: [PATCH] various stability improvements --- package.json | 2 +- hmr-client.js => sapper-dev-client.js | 16 ++- src/cli/dev.ts | 10 +- src/core/create_app.ts | 6 +- src/core/create_template.ts | 39 -------- src/core/index.ts | 3 +- src/middleware/index.ts | 137 +++++++++++++++----------- 7 files changed, 102 insertions(+), 111 deletions(-) rename hmr-client.js => sapper-dev-client.js (56%) delete mode 100644 src/core/create_template.ts diff --git a/package.json b/package.json index 93233aa..a0d6210 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "middleware.js", "runtime", "runtime.js", - "hmr-client.js", + "sapper-dev-client.js", "webpack" ], "directories": { diff --git a/hmr-client.js b/sapper-dev-client.js similarity index 56% rename from hmr-client.js rename to sapper-dev-client.js index 88938dc..d1b59e1 100644 --- a/hmr-client.js +++ b/sapper-dev-client.js @@ -3,7 +3,7 @@ let source; function check() { if (module.hot.status() === 'idle') { module.hot.check(true).then(modules => { - console.log(`HMR updated`); + console.log(`[SAPPER] applied HMR update`); }); } } @@ -11,16 +11,26 @@ function check() { export function connect(port) { if (source || !window.EventSource) return; - source = new EventSource(`http://localhost:${port}/hmr`); + source = new EventSource(`http://localhost:${port}/__sapper__`); + + window.source = source; source.onopen = function(event) { - console.log(`HMR connected`); + console.log(`[SAPPER] dev client connected`); + }; + + source.onerror = function(error) { + console.error(error); }; source.onmessage = function(event) { const data = JSON.parse(event.data); if (!data) return; // just a heartbeat + if (data.action === 'reload') { + window.location.reload(); + } + if (data.status === 'completed') { check(); } diff --git a/src/cli/dev.ts b/src/cli/dev.ts index 421f1bd..0cc7798 100644 --- a/src/cli/dev.ts +++ b/src/cli/dev.ts @@ -8,7 +8,7 @@ import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; import { wait_for_port } from './utils'; import { dest } from '../config'; -import { create_compilers, create_app, create_routes, create_serviceworker, create_template } from 'sapper/core.js'; +import { create_compilers, create_app, create_routes, create_serviceworker } from 'sapper/core.js'; type Deferred = { promise?: Promise; @@ -31,11 +31,12 @@ function create_hot_update_server(port: number, interval = 10000) { const clients = new Set(); const server = http.createServer((req, res) => { - if (req.url !== '/hmr') return; + if (req.url !== '/__sapper__') return; req.socket.setKeepAlive(true); res.writeHead(200, { 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'Cache-Control', 'Content-Type': 'text/event-stream;charset=utf-8', 'Cache-Control': 'no-cache, no-transform', 'Connection': 'keep-alive', @@ -103,8 +104,9 @@ export default async function dev() { }); watch_files('app/template.html', ['change'], () => { - const template = create_template(); - // TODO reload current page? + hot_update_server.send({ + action: 'reload' + }); }); let proc: child_process.ChildProcess; diff --git a/src/core/create_app.ts b/src/core/create_app.ts index 79165ff..42eccce 100644 --- a/src/core/create_app.ts +++ b/src/core/create_app.ts @@ -56,14 +56,14 @@ function generate_client(routes: Route[], dev_port?: number) { ];`.replace(/^\t\t/gm, '').trim(); if (dev()) { - const hmr_client = posixify( - path.resolve(__dirname, 'hmr-client.js') + const sapper_dev_client = posixify( + path.resolve(__dirname, 'sapper-dev-client.js') ); code += ` if (module.hot) { - import('${hmr_client}').then(client => { + import('${sapper_dev_client}').then(client => { client.connect(${dev_port}); }); }`.replace(/^\t{3}/gm, ''); diff --git a/src/core/create_template.ts b/src/core/create_template.ts deleted file mode 100644 index 3ca5da9..0000000 --- a/src/core/create_template.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as fs from 'fs'; -import chalk from 'chalk'; -import framer from 'code-frame'; -import { locate } from 'locate-character'; - -function error(e: any) { - if (e.title) console.error(chalk.bold.red(e.title)); - if (e.body) console.error(chalk.red(e.body)); - if (e.url) console.error(chalk.cyan(e.url)); - if (e.frame) console.error(chalk.grey(e.frame)); - - process.exit(1); -} - -export default function create_templates() { - const template = fs.readFileSync(`app/template.html`, 'utf-8'); - - const index = template.indexOf('%sapper.main%'); - if (index !== -1) { - // TODO remove this in a future version - const { line, column } = locate(template, index, { offsetLine: 1 }); - const frame = framer(template, line, column); - - error({ - title: `app/template.html`, - body: `${scripts}`; - const page = template.render({ - scripts, - html, - head: `${head}`, - styles: (css && css.code ? `` : '') - }); + const page = template() + .replace('%sapper.scripts%', scripts) + .replace('%sapper.html%', html) + .replace('%sapper.head%', `${head}`) + .replace('%sapper.styles%', (css && css.code ? `` : '')); res.end(page); @@ -271,17 +286,19 @@ function get_route_handler(chunks: Record, routes: RouteObject[] const { head, css, html } = rendered; - res.end(template.render({ - scripts: ``, - html, - head: `${head}`, - styles: (css && css.code ? `` : '') - })); + const page = template() + .replace('%sapper.scripts%', ``) + .replace('%sapper.html%', html) + .replace('%sapper.head%', `${head}`) + .replace('%sapper.styles%', (css && css.code ? `` : '')); + + res.end(page); } const error_route = routes.find((route: RouteObject) => route.error === '5xx'); function handle_error(req: Req, res: ServerResponse, statusCode: number, message: Error | string) { + // TODO lot of repetition between this and handle_not_found if (statusCode >= 400 && statusCode < 500) { return handle_not_found(req, res, statusCode, message); } @@ -298,12 +315,13 @@ function get_route_handler(chunks: Record, routes: RouteObject[] const { head, css, html } = rendered; - res.end(template.render({ - scripts: ``, - html, - head: `${head}`, - styles: (css && css.code ? `` : '') - })); + const page = template() + .replace('%sapper.scripts%', ``) + .replace('%sapper.html%', html) + .replace('%sapper.head%', `${head}`) + .replace('%sapper.styles%', (css && css.code ? `` : '')); + + res.end(page); } return function find_route(req: Req, res: ServerResponse) { @@ -353,10 +371,11 @@ function try_serialize(data: any) { } } -function try_read(file: string) { +function exists(file: string) { try { - return fs.readFileSync(file, 'utf-8'); + fs.statSync(file); + return true; } catch (err) { - return null; + return false; } } \ No newline at end of file