-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathentry.server.tsx
More file actions
75 lines (65 loc) · 1.94 KB
/
entry.server.tsx
File metadata and controls
75 lines (65 loc) · 1.94 KB
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
import { PassThrough } from 'stream'
import { createReadableStreamFromReadable } from '@react-router/node'
import { isbot } from 'isbot'
import {
renderToPipeableStream,
type RenderToPipeableStreamOptions,
} from 'react-dom/server'
import { I18nextProvider } from 'react-i18next'
import {
type RouterContextProvider,
ServerRouter,
type EntryContext,
} from 'react-router'
import { getEnv, init } from './lib/env.server'
import { getInstance } from './middleware/i18next'
export const STREAM_TIMEOUT = 5_000
init()
global.ENV = getEnv()
export default async function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
entryContext: EntryContext,
routerContext: RouterContextProvider,
) {
return new Promise((resolve, reject) => {
let shellRendered = false
let userAgent = request.headers.get('user-agent')
let readyOption: keyof RenderToPipeableStreamOptions =
(userAgent && isbot(userAgent)) || entryContext.isSpaMode
? 'onAllReady'
: 'onShellReady'
let didError = false
const { pipe, abort } = renderToPipeableStream(
<I18nextProvider i18n={getInstance(routerContext)}>
<ServerRouter context={entryContext} url={request.url} />
</I18nextProvider>,
{
[readyOption]: () => {
shellRendered = true
const body = new PassThrough()
const stream = createReadableStreamFromReadable(body)
responseHeaders.set('Content-Type', 'text/html')
resolve(
new Response(stream, {
headers: responseHeaders,
status: didError ? 500 : responseStatusCode,
}),
)
pipe(body)
},
onShellError: (err: unknown) => {
reject(err)
},
onError: (error: unknown) => {
didError = true
if (shellRendered) console.error(error)
},
},
)
// Automatically timeout the React renderer after 6 seconds, which ensures
// React has enough time to flush down the rejected boundary contents
setTimeout(abort, STREAM_TIMEOUT + 1_000)
})
}