refactor: improve Cloudflare streaming HTML response in server entry

This commit is contained in:
harishvishwa 2025-06-18 11:51:31 +05:30
parent eda10b1212
commit 38b85ae2be

View File

@ -13,66 +13,70 @@ export default async function handleRequest(
remixContext: EntryContext,
_loadContext: AppLoadContext,
) {
const readable = await renderToReadableStream(<RemixServer context={remixContext} url={request.url} />, {
signal: request.signal,
onError(error: unknown) {
console.error(error);
responseStatusCode = 500;
},
});
try {
const stream = await renderToReadableStream(
<RemixServer context={remixContext} url={request.url} />,
{
signal: request.signal,
onError(error: unknown) {
console.error('Render error:', error);
responseStatusCode = 500;
},
},
);
const body = new ReadableStream({
start(controller) {
const head = renderHeadToString({ request, remixContext, Head });
const htmlStream = new ReadableStream({
async start(controller) {
try {
const head = renderHeadToString({ request, remixContext, Head });
controller.enqueue(
new Uint8Array(
new TextEncoder().encode(
`<!DOCTYPE html><html lang="en" data-theme="${themeStore.value}"><head>${head}</head><body><div id="root" class="w-full h-full">`,
),
),
);
controller.enqueue(
encodeString(
`<!DOCTYPE html><html lang="en" data-theme="${themeStore.value}"><head>${head}</head><body><div id="root" class="w-full h-full">`
)
);
const reader = readable.getReader();
function read() {
reader
.read()
.then(({ done, value }) => {
if (done) {
controller.enqueue(new Uint8Array(new TextEncoder().encode(`</div></body></html>`)));
controller.close();
return;
}
const reader = stream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
controller.enqueue(value);
read();
})
.catch((error) => {
controller.error(error);
readable.cancel();
});
}
read();
},
}
cancel() {
readable.cancel();
},
});
controller.enqueue(encodeString(`</div></body></html>`));
controller.close();
} catch (err) {
controller.error(err);
stream.cancel();
}
},
if (isbot(request.headers.get('user-agent') || '')) {
await readable.allReady;
cancel() {
stream.cancel();
},
});
if (isbot(request.headers.get('user-agent') || '')) {
await stream.allReady;
}
responseHeaders.set('Content-Type', 'text/html');
responseHeaders.set('Cross-Origin-Embedder-Policy', 'require-corp');
responseHeaders.set('Cross-Origin-Opener-Policy', 'same-origin');
return new Response(htmlStream, {
status: responseStatusCode,
headers: responseHeaders,
});
} catch (error) {
console.error('Unhandled rendering error:', error);
return new Response('Internal Server Error', { status: 500 });
}
responseHeaders.set('Content-Type', 'text/html');
responseHeaders.set('Cross-Origin-Embedder-Policy', 'require-corp');
responseHeaders.set('Cross-Origin-Opener-Policy', 'same-origin');
return new Response(body, {
headers: responseHeaders,
status: responseStatusCode,
});
}
function encodeString(content: string): Uint8Array {
return new TextEncoder().encode(content);
}