From f99c0e92e5a2cf00ef6302c14b57ab6d58c0cc44 Mon Sep 17 00:00:00 2001 From: Katalina T Date: Wed, 5 Jun 2019 12:50:27 -0500 Subject: [PATCH] [ui-server]: add dev-server hotreloader --- packages/roleypoly-ui-server/package.json | 10 ++-- .../roleypoly-ui-server/src/dev-server.ts | 17 ++++++ packages/roleypoly-ui-server/src/index.ts | 52 +++++++++++++------ 3 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 packages/roleypoly-ui-server/src/dev-server.ts diff --git a/packages/roleypoly-ui-server/package.json b/packages/roleypoly-ui-server/package.json index fbe7c1b..be4a5d5 100644 --- a/packages/roleypoly-ui-server/package.json +++ b/packages/roleypoly-ui-server/package.json @@ -9,14 +9,16 @@ "start": "node lib/index.js" }, "dependencies": { - "koa": "^2.7.0", - "koa-better-router": "^2.1.1", - "kompression": "richard-riverford/kompression#0d4480c", "@roleypoly/ui": "2.0.0", "chalk": "^2.4.2", - "dotenv": "^8.0.0" + "dotenv": "^8.0.0", + "koa": "^2.7.0", + "koa-better-router": "^2.1.1", + "kompression": "richard-riverford/kompression#0d4480c" }, "devDependencies": { + "chalk": "^2.4.2", + "chokidar": "^3.0.1", "lint-staged": "^8.1.7", "tslint": "^5.17.0", "typescript": "^3.5.1" diff --git a/packages/roleypoly-ui-server/src/dev-server.ts b/packages/roleypoly-ui-server/src/dev-server.ts new file mode 100644 index 0000000..0e10970 --- /dev/null +++ b/packages/roleypoly-ui-server/src/dev-server.ts @@ -0,0 +1,17 @@ +import chokidar from 'chokidar' +import chalk from 'chalk' + +export const hotReloader = (watchPath: string, callback: () => Function): Function => { + const watcher = chokidar.watch(watchPath, { ignoreInitial: true }) + let hotMiddleware = callback() + + watcher.on('all', (_: string, file: string) => { + delete require.cache[file] + + console.log(`[ ${chalk.red`dev-server`} ] hot reloaded, file changed:`, file) + hotMiddleware = callback() + }) + + console.log(`[ ${chalk.red`dev-server`} ] hot reloading started.`) + return (...args: any) => hotMiddleware(...args) +} diff --git a/packages/roleypoly-ui-server/src/index.ts b/packages/roleypoly-ui-server/src/index.ts index e95840f..1fcad4e 100644 --- a/packages/roleypoly-ui-server/src/index.ts +++ b/packages/roleypoly-ui-server/src/index.ts @@ -1,7 +1,7 @@ import 'dotenv/config' import Koa, { Context } from 'koa' -import mappings from '@roleypoly/ui/mappings' import connector from '@roleypoly/ui/connector' +import { Mappings } from '@roleypoly/ui/mappings' import betterRouter from 'koa-better-router' import compress from 'kompression' @@ -17,43 +17,65 @@ export type Router = { const app = new Koa() -async function start () { +const isDev = process.env.NODE_ENV === 'development' + +function loadRoutes (next: any, routeMapping: Mappings): Function { const router: Router = betterRouter().loadMethods() - - app.use(compress()) - - const next = connector({ dev: process.env.NODE_ENV === 'development' }) - await next.prepare() const nextHandler = next.getRequestHandler() // UI dynamic mappings - for (let mapping in mappings) { - const { path, noAutoFix, custom } = mappings[mapping] as { path: string, noAutoFix?: boolean, custom?: (router: Router) => void } + for (let mapping in routeMapping) { + const { path, noAutoFix, custom } = routeMapping[mapping] - // render the path if mapping is GET-ted + // render the path if mapping is GET-ted router.get(mapping, (ctx: Context) => { ctx.status = 200 return next.render(ctx.req, ctx.res, path, { ...ctx.query, ...ctx.params }) }) - // redirect the inverse path if there isn't a parameter + // redirect the inverse path if there isn't a parameter if (!noAutoFix) { router.get(path, (ctx: Context) => ctx.redirect(mapping)) } - // all else, if custom exists, we call it. - // this solves edge cases per route. + // all else, if custom exists, we call it. + // this solves edge cases per route. if (custom !== undefined) { - custom(router) + custom(router as any) } } - // handle all else +// handle all else router.get('*', async (ctx: Context) => { await nextHandler(ctx.req, ctx.res) ctx.respond = false }) + return router.middleware() +} + +async function start () { + app.use(compress()) + + const next = connector({ dev: isDev }) + await next.prepare() + + const mappings = require('@roleypoly/ui/mappings') + let mw = loadRoutes(next, mappings) + + if (isDev) { + const { hotReloader } = require('./dev-server') + mw = hotReloader( + require.resolve('@roleypoly/ui/mappings'), + () => { + const newMappings = require('@roleypoly/ui/mappings') + return loadRoutes(next, newMappings) + } + ) + } + + app.use(mw as any) + app.listen(process.env.UI_PORT || '6768') }