This repository has been archived on 2024-07-16. You can view files and clone it, but cannot push or open issues or pull requests.
www.local-ip.sh/app/entry.server.tsx

114 lines
3.0 KiB
TypeScript
Raw Normal View History

2023-12-11 14:19:17 +00:00
import { PassThrough } from "node:stream";
import type { AppLoadContext, EntryContext } from "@remix-run/node";
import { createReadableStreamFromReadable } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import isbot from "isbot";
import { renderToPipeableStream } from "react-dom/server";
const ABORT_DELAY = 5_000;
export default function handleRequest(
2023-12-12 23:15:37 +00:00
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
loadContext: AppLoadContext,
2023-12-11 14:19:17 +00:00
) {
2023-12-12 23:15:37 +00:00
return isbot(request.headers.get("user-agent"))
2023-12-22 22:59:14 +00:00
? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext)
: handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext);
2023-12-11 14:19:17 +00:00
}
function handleBotRequest(
2023-12-12 23:15:37 +00:00
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
2023-12-11 14:19:17 +00:00
) {
2023-12-12 23:15:37 +00:00
return new Promise((resolve, reject) => {
let shellRendered = false;
const { pipe, abort } = renderToPipeableStream(
2023-12-22 22:59:14 +00:00
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />,
2023-12-12 23:15:37 +00:00
{
onAllReady() {
shellRendered = true;
const body = new PassThrough();
const stream = createReadableStreamFromReadable(body);
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
responseHeaders.set("Content-Type", "text/html");
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
resolve(
new Response(stream, {
headers: responseHeaders,
status: responseStatusCode,
}),
);
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
pipe(body);
},
onShellError(error: unknown) {
reject(error);
},
onError(error: unknown) {
responseStatusCode = 500;
// Log streaming rendering errors from inside the shell. Don't log
// errors encountered during initial shell rendering since they'll
// reject and get logged in handleDocumentRequest.
if (shellRendered) {
console.error(error);
}
},
},
);
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
setTimeout(abort, ABORT_DELAY);
});
2023-12-11 14:19:17 +00:00
}
function handleBrowserRequest(
2023-12-12 23:15:37 +00:00
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
2023-12-11 14:19:17 +00:00
) {
2023-12-12 23:15:37 +00:00
return new Promise((resolve, reject) => {
let shellRendered = false;
const { pipe, abort } = renderToPipeableStream(
2023-12-22 22:59:14 +00:00
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />,
2023-12-12 23:15:37 +00:00
{
onShellReady() {
shellRendered = true;
const body = new PassThrough();
const stream = createReadableStreamFromReadable(body);
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
responseHeaders.set("Content-Type", "text/html");
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
resolve(
new Response(stream, {
headers: responseHeaders,
status: responseStatusCode,
}),
);
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
pipe(body);
},
onShellError(error: unknown) {
reject(error);
},
onError(error: unknown) {
responseStatusCode = 500;
// Log streaming rendering errors from inside the shell. Don't log
// errors encountered during initial shell rendering since they'll
// reject and get logged in handleDocumentRequest.
if (shellRendered) {
console.error(error);
}
},
},
);
2023-12-11 14:19:17 +00:00
2023-12-12 23:15:37 +00:00
setTimeout(abort, ABORT_DELAY);
});
2023-12-11 14:19:17 +00:00
}