|
import type { AppLoadContext, EntryContext } from '@remix-run/cloudflare'; |
|
import { RemixServer } from '@remix-run/react'; |
|
import { isbot } from 'isbot'; |
|
import { renderToReadableStream } from 'react-dom/server'; |
|
import { renderHeadToString } from 'remix-island'; |
|
import { Head } from './root'; |
|
import { themeStore } from '~/lib/stores/theme'; |
|
|
|
export default async function handleRequest( |
|
request: Request, |
|
responseStatusCode: number, |
|
responseHeaders: Headers, |
|
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; |
|
}, |
|
}); |
|
|
|
const body = new ReadableStream({ |
|
start(controller) { |
|
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">`, |
|
), |
|
), |
|
); |
|
|
|
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; |
|
} |
|
|
|
controller.enqueue(value); |
|
read(); |
|
}) |
|
.catch((error) => { |
|
controller.error(error); |
|
readable.cancel(); |
|
}); |
|
} |
|
read(); |
|
}, |
|
|
|
cancel() { |
|
readable.cancel(); |
|
}, |
|
}); |
|
|
|
if (isbot(request.headers.get('user-agent') || '')) { |
|
await readable.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(body, { |
|
headers: responseHeaders, |
|
status: responseStatusCode, |
|
}); |
|
} |
|
|