generated from stormkit-io/monorepo-template-react
-
Notifications
You must be signed in to change notification settings - Fork 1
/
entry-server.tsx
94 lines (85 loc) · 2.92 KB
/
entry-server.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { StaticRouter } from 'react-router-dom/server'
import { renderToString } from 'react-dom/server'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import serverless from '@stormkit/serverless'
import createRoutes from './routes'
import Context from './context'
import App from './App'
interface RenderReturn {
status: number
content: string
head: string
}
export type RenderFunction = (url: string) => Promise<RenderReturn>
const defaultSEO: SEO = {
title: 'Vite + React (SSR, SSG, SPA)',
description: 'Mono repo template for apps needing ssr, ssg and/or spa.',
domain: {
name: '',
url: '',
},
twitter: {
card: 'summary_large_image',
creator: '@savasvedova',
},
}
export const render: RenderFunction = async (url) => {
const { routes, head, context } = await createRoutes(url)
const tags = {
...defaultSEO,
...head,
}
// Prefix the title with the domain.name property.
tags.title =
`${tags.domain?.name ? tags.domain.name + ' | ' : ''}` + tags.title
return {
status: 200,
content:
renderToString(
<Context.Provider value={context}>
<StaticRouter location={url}>
<App routes={routes} />
</StaticRouter>
</Context.Provider>,
) +
(context
? `<script>window.CONTEXT = ${JSON.stringify(context)}</script>`
: ''),
head: [
`<title>${tags.title}</title>`,
`<meta charset="utf-8" />`,
`<meta name="viewport" content="width=device-width, initial-scale=1.0" />`,
`<meta name="description" content="${tags.description}" />`,
`<meta property="og:title" content="${tags.title}" />`,
`<meta property="og:url" content="${tags.domain?.url}" />`,
`<meta property="og:description" content="${tags.description}" />`,
`<meta property="og:image" content="${tags.domain?.url}/logo.svg" />`,
`<meta name="twitter:card" content="${tags.twitter!.card}" />`,
`<meta name="twitter:creator" content="${tags.twitter!.creator}" />`,
`<meta name="twitter:title" content="${tags.title}" />`,
`<meta name="twitter:description" content="${tags.description}" />`,
`<link rel="icon" type="image/svg+xml" href="/logo.svg" />`,
]
.join('\n')
.trim(),
}
}
// This handler add support for Stormkit environment. This is
// the entry point of the serverless application.
export const handler = serverless(async (req: any, res: any) => {
// We are in assets folder
const dir = path.dirname(fileURLToPath(import.meta.url))
const html = fs.readFileSync(path.join(dir, './index.html'), 'utf-8')
const { status, content, head } = await render(
req.url?.split(/\?#/)[0] || '/',
)
res.writeHead(status, 'OK', { 'Content-Type': 'text/html; charset=utf-8' })
res.write(
html
.replace('</head>', `${head}</head>`)
.replace(`<div id="root"></div>`, `<div id="root">${content}</div>`),
)
res.end()
})