Skip to content
This repository was archived by the owner on Jan 4, 2024. It is now read-only.

Commit 624face

Browse files
committed
feat: upgrade entry.server from remix v1.18
1 parent 2b80ddc commit 624face

File tree

1 file changed

+123
-10
lines changed

1 file changed

+123
-10
lines changed

app/entry.server.tsx

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,142 @@
1+
/**
2+
* By default, Remix will handle generating the HTTP Response for you.
3+
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4+
* For more information, see https://remix.run/file-conventions/entry.server
5+
*/
6+
7+
import { PassThrough } from "node:stream";
8+
9+
import type { AppLoadContext, EntryContext } from "@remix-run/node";
10+
import { Response } from "@remix-run/node";
111
import { RemixServer } from "@remix-run/react";
2-
import { renderToString } from "react-dom/server";
12+
import isbot from "isbot";
13+
import { renderToPipeableStream } from "react-dom/server";
314

415
import { seoRouteHandlers } from "./seo-routes.server";
516

6-
import type { EntryContext } from "@remix-run/node";
17+
const ABORT_DELAY = 5_000;
718

819
export default async function handleRequest(
920
request: Request,
1021
responseStatusCode: number,
1122
responseHeaders: Headers,
12-
remixContext: EntryContext
23+
remixContext: EntryContext,
24+
loadContext: AppLoadContext
1325
) {
1426
for (const handler of seoRouteHandlers) {
1527
const seoRouteResponse = await handler(request, remixContext);
1628
if (seoRouteResponse) return seoRouteResponse;
1729
}
1830

19-
const markup = renderToString(
20-
<RemixServer context={remixContext} url={request.url} />
21-
);
31+
return isbot(request.headers.get("user-agent"))
32+
? handleBotRequest(
33+
request,
34+
responseStatusCode,
35+
responseHeaders,
36+
remixContext
37+
)
38+
: handleBrowserRequest(
39+
request,
40+
responseStatusCode,
41+
responseHeaders,
42+
remixContext
43+
);
44+
}
45+
46+
function handleBotRequest(
47+
request: Request,
48+
responseStatusCode: number,
49+
responseHeaders: Headers,
50+
remixContext: EntryContext
51+
) {
52+
return new Promise((resolve, reject) => {
53+
let shellRendered = false;
54+
const { pipe, abort } = renderToPipeableStream(
55+
<RemixServer
56+
context={remixContext}
57+
url={request.url}
58+
abortDelay={ABORT_DELAY}
59+
/>,
60+
{
61+
onAllReady() {
62+
shellRendered = true;
63+
const body = new PassThrough();
64+
65+
responseHeaders.set("Content-Type", "text/html");
66+
67+
resolve(
68+
new Response(body, {
69+
headers: responseHeaders,
70+
status: responseStatusCode,
71+
})
72+
);
73+
74+
pipe(body);
75+
},
76+
onShellError(error: unknown) {
77+
reject(error);
78+
},
79+
onError(error: unknown) {
80+
responseStatusCode = 500;
81+
// Log streaming rendering errors from inside the shell. Don't log
82+
// errors encountered during initial shell rendering since they'll
83+
// reject and get logged in handleDocumentRequest.
84+
if (shellRendered) {
85+
console.error(error);
86+
}
87+
},
88+
}
89+
);
90+
91+
setTimeout(abort, ABORT_DELAY);
92+
});
93+
}
94+
95+
function handleBrowserRequest(
96+
request: Request,
97+
responseStatusCode: number,
98+
responseHeaders: Headers,
99+
remixContext: EntryContext
100+
) {
101+
return new Promise((resolve, reject) => {
102+
let shellRendered = false;
103+
const { pipe, abort } = renderToPipeableStream(
104+
<RemixServer
105+
context={remixContext}
106+
url={request.url}
107+
abortDelay={ABORT_DELAY}
108+
/>,
109+
{
110+
onShellReady() {
111+
shellRendered = true;
112+
const body = new PassThrough();
113+
114+
responseHeaders.set("Content-Type", "text/html");
115+
116+
resolve(
117+
new Response(body, {
118+
headers: responseHeaders,
119+
status: responseStatusCode,
120+
})
121+
);
22122

23-
responseHeaders.set("Content-Type", "text/html");
123+
pipe(body);
124+
},
125+
onShellError(error: unknown) {
126+
reject(error);
127+
},
128+
onError(error: unknown) {
129+
responseStatusCode = 500;
130+
// Log streaming rendering errors from inside the shell. Don't log
131+
// errors encountered during initial shell rendering since they'll
132+
// reject and get logged in handleDocumentRequest.
133+
if (shellRendered) {
134+
console.error(error);
135+
}
136+
},
137+
}
138+
);
24139

25-
return new Response("<!DOCTYPE html>" + markup, {
26-
headers: responseHeaders,
27-
status: responseStatusCode,
140+
setTimeout(abort, ABORT_DELAY);
28141
});
29142
}

0 commit comments

Comments
 (0)