2023-11-04 13:02:08 +00:00
|
|
|
import fs from 'fs'
|
|
|
|
import path from 'path'
|
|
|
|
|
|
|
|
import { fileURLToPath } from 'url'
|
|
|
|
|
|
|
|
import Koa from 'koa'
|
|
|
|
import koaConnect from 'koa-connect'
|
|
|
|
|
|
|
|
import { createServer as createViteServer } from 'vite'
|
|
|
|
|
|
|
|
const HOST_NAME = '127.0.0.1'
|
|
|
|
const APP_PORT = 1007
|
|
|
|
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
|
|
|
2023-11-07 08:26:10 +00:00
|
|
|
// Inject teleports in template
|
|
|
|
const injectTeleports = (
|
|
|
|
html: string,
|
|
|
|
teleports: {
|
|
|
|
'#teleported': string
|
|
|
|
}
|
|
|
|
) => {
|
|
|
|
// return html
|
|
|
|
return html.replace('<!--teleports-->', teleports['#teleported'])
|
|
|
|
}
|
|
|
|
|
2023-11-06 14:07:54 +00:00
|
|
|
;(async (hmrPort) => {
|
2023-11-04 13:02:08 +00:00
|
|
|
const app = new Koa()
|
|
|
|
|
|
|
|
const vite = await createViteServer({
|
2023-11-06 14:07:54 +00:00
|
|
|
server: {
|
|
|
|
middlewareMode: true,
|
|
|
|
watch: {
|
|
|
|
// During tests we edit the files too fast and sometimes chokidar
|
|
|
|
// misses change events, so enforce polling for consistency
|
|
|
|
usePolling: true,
|
|
|
|
interval: 107,
|
|
|
|
},
|
|
|
|
hmr: {
|
|
|
|
port: hmrPort,
|
|
|
|
},
|
|
|
|
},
|
2023-11-06 12:55:14 +00:00
|
|
|
appType: 'custom',
|
2023-11-04 13:02:08 +00:00
|
|
|
})
|
|
|
|
|
2023-11-07 08:26:18 +00:00
|
|
|
// Parse accept-language
|
|
|
|
const parseAcceptLanguage = (acceptLanguage: string) => {
|
2023-11-07 08:26:10 +00:00
|
|
|
const languages = acceptLanguage.split(',')
|
|
|
|
const language = languages[0]
|
|
|
|
const country = language.split('-')[1]
|
|
|
|
return { language, country }
|
|
|
|
}
|
|
|
|
|
2023-11-04 13:02:08 +00:00
|
|
|
app.use(koaConnect(vite.middlewares))
|
|
|
|
|
|
|
|
app.use(async (ctx) => {
|
2023-11-07 08:26:10 +00:00
|
|
|
const { language, country } = parseAcceptLanguage(
|
|
|
|
ctx.request.headers['accept-language'] as string
|
|
|
|
)
|
2023-11-04 13:02:08 +00:00
|
|
|
try {
|
|
|
|
let template = fs.readFileSync(
|
|
|
|
path.resolve(__dirname, 'index.html'),
|
|
|
|
'utf-8'
|
|
|
|
)
|
|
|
|
|
|
|
|
template = await vite.transformIndexHtml(ctx.path, template)
|
|
|
|
|
|
|
|
const { render } = await vite.ssrLoadModule('/src/entry-server.ts')
|
|
|
|
|
2023-11-07 08:26:10 +00:00
|
|
|
const [renderedHtml, renderedPinia, renderedLinks, renderedTeleports] =
|
|
|
|
await render(
|
|
|
|
ctx,
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
language,
|
|
|
|
country,
|
|
|
|
}
|
|
|
|
)
|
2023-11-04 13:02:08 +00:00
|
|
|
|
2023-11-07 08:26:10 +00:00
|
|
|
const html = injectTeleports(template, renderedTeleports)
|
2023-11-05 07:13:40 +00:00
|
|
|
.replace('<!--preload-links-->', renderedLinks)
|
2023-11-04 13:02:08 +00:00
|
|
|
.replace('<!--ssr-outlet-->', renderedHtml)
|
2023-11-05 07:13:40 +00:00
|
|
|
.replace('__pinia', renderedPinia)
|
2023-11-04 13:02:08 +00:00
|
|
|
|
|
|
|
ctx.type = 'text/html'
|
|
|
|
ctx.body = html
|
|
|
|
} catch (e) {
|
2023-11-04 14:06:19 +00:00
|
|
|
vite && vite.ssrFixStacktrace(e as Error)
|
2023-11-04 13:02:08 +00:00
|
|
|
ctx.throw(500, e as Error)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
app.listen(APP_PORT, () => {
|
2023-11-06 12:55:14 +00:00
|
|
|
console.log(`Server is listening on http://${HOST_NAME}:${APP_PORT}`)
|
2023-11-04 13:02:08 +00:00
|
|
|
})
|
|
|
|
})()
|