[ui-server]: add dev-server hotreloader

This commit is contained in:
41666 2019-06-05 12:50:27 -05:00
parent be0a34cc5b
commit f99c0e92e5
No known key found for this signature in database
GPG key ID: DE08FAA8925DC747
3 changed files with 60 additions and 19 deletions

View file

@ -9,14 +9,16 @@
"start": "node lib/index.js" "start": "node lib/index.js"
}, },
"dependencies": { "dependencies": {
"koa": "^2.7.0",
"koa-better-router": "^2.1.1",
"kompression": "richard-riverford/kompression#0d4480c",
"@roleypoly/ui": "2.0.0", "@roleypoly/ui": "2.0.0",
"chalk": "^2.4.2", "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": { "devDependencies": {
"chalk": "^2.4.2",
"chokidar": "^3.0.1",
"lint-staged": "^8.1.7", "lint-staged": "^8.1.7",
"tslint": "^5.17.0", "tslint": "^5.17.0",
"typescript": "^3.5.1" "typescript": "^3.5.1"

View file

@ -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)
}

View file

@ -1,7 +1,7 @@
import 'dotenv/config' import 'dotenv/config'
import Koa, { Context } from 'koa' import Koa, { Context } from 'koa'
import mappings from '@roleypoly/ui/mappings'
import connector from '@roleypoly/ui/connector' import connector from '@roleypoly/ui/connector'
import { Mappings } from '@roleypoly/ui/mappings'
import betterRouter from 'koa-better-router' import betterRouter from 'koa-better-router'
import compress from 'kompression' import compress from 'kompression'
@ -17,43 +17,65 @@ export type Router = {
const app = new Koa() 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() const router: Router = betterRouter().loadMethods()
app.use(compress())
const next = connector({ dev: process.env.NODE_ENV === 'development' })
await next.prepare()
const nextHandler = next.getRequestHandler() const nextHandler = next.getRequestHandler()
// UI dynamic mappings // UI dynamic mappings
for (let mapping in mappings) { for (let mapping in routeMapping) {
const { path, noAutoFix, custom } = mappings[mapping] as { path: string, noAutoFix?: boolean, custom?: (router: Router) => void } 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) => { router.get(mapping, (ctx: Context) => {
ctx.status = 200 ctx.status = 200
return next.render(ctx.req, ctx.res, path, { ...ctx.query, ...ctx.params }) 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) { if (!noAutoFix) {
router.get(path, (ctx: Context) => ctx.redirect(mapping)) router.get(path, (ctx: Context) => ctx.redirect(mapping))
} }
// all else, if custom exists, we call it. // all else, if custom exists, we call it.
// this solves edge cases per route. // this solves edge cases per route.
if (custom !== undefined) { if (custom !== undefined) {
custom(router) custom(router as any)
} }
} }
// handle all else // handle all else
router.get('*', async (ctx: Context) => { router.get('*', async (ctx: Context) => {
await nextHandler(ctx.req, ctx.res) await nextHandler(ctx.req, ctx.res)
ctx.respond = false 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') app.listen(process.env.UI_PORT || '6768')
} }