From 51efb7aa0a8e0034bbd3a01729eab0fe1b7143ae Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Fri, 29 Mar 2024 18:29:32 +0100 Subject: [PATCH] chore: add entry.server.tsx to functions template --- remix.init/functions/app/entry.server.tsx | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 remix.init/functions/app/entry.server.tsx diff --git a/remix.init/functions/app/entry.server.tsx b/remix.init/functions/app/entry.server.tsx new file mode 100644 index 0000000..16d4978 --- /dev/null +++ b/remix.init/functions/app/entry.server.tsx @@ -0,0 +1,79 @@ +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( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext +) { + const bot = isbot(request.headers.get("user-agent")); + return new Promise((resolve, reject) => { + let shellRendered = false; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady() { + if (!bot) { + shellRendered = true; + responseHeaders.set("Content-Type", "text/html"); + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ); + pipe(body); + } + }, + onShellError(error: unknown) { + reject(error); + }, + onAllReady() { + // Avoid a bug where responses aren't flushed if there's an outstanding timer. + clearTimeout(timer); + if (bot) { + shellRendered = true; + responseHeaders.set("Content-Type", "text/html"); + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ); + pipe(body); + } + }, + 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); + } + }, + } + ); + + const timer = setTimeout(() => { + abort(); + }, ABORT_DELAY); + }); +}