mirror of
https://github.com/BradNut/awesome-uses
synced 2025-09-08 17:40:31 +00:00
81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
import type { EntryContext } from '@remix-run/node';
|
|
import { RemixServer } from '@remix-run/react';
|
|
import { renderToReadableStream } from 'react-dom/server';
|
|
|
|
const ABORT_DELAY = 5000;
|
|
|
|
export async function streamToText(stream: ReadableStream<Uint8Array>): Promise<string> {
|
|
let result = '';
|
|
const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
|
|
while (true) { // eslint-disable-line no-constant-condition
|
|
const { done, value } = await reader.read();
|
|
if (done) {
|
|
break;
|
|
}
|
|
|
|
result += value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
type CachedResponse = {
|
|
html: string;
|
|
date: Date;
|
|
}
|
|
const cache = new Map<string, CachedResponse>();
|
|
|
|
export default async function handleRequest(
|
|
request: Request,
|
|
responseStatusCode: number,
|
|
responseHeaders: Headers,
|
|
remixContext: EntryContext
|
|
) {
|
|
// check if we have a cached response in memory
|
|
const cachedResponse = cache.get(request.url);
|
|
if (cachedResponse) {
|
|
// console.log('Serving from cache', request.url);
|
|
// if we have a cached response, check if it's less than 5 seconds old
|
|
const now = new Date();
|
|
const diff = now.getTime() - cachedResponse.date.getTime();
|
|
if (true || diff < 5000) {
|
|
// if it's less than 5 seconds old, return the cached response
|
|
responseHeaders.set('Content-Type', 'text/html');
|
|
return new Response(cachedResponse.html, {
|
|
headers: responseHeaders,
|
|
status: responseStatusCode,
|
|
});
|
|
}
|
|
}
|
|
|
|
let didError = false;
|
|
const chunks: Uint8Array[] = [];
|
|
|
|
const body = await renderToReadableStream(
|
|
<RemixServer context={remixContext} url={request.url} />,
|
|
{
|
|
onError: (error: unknown) => {
|
|
didError = true;
|
|
console.error(error);
|
|
}
|
|
}
|
|
);
|
|
|
|
// tee the stream so we can cache it and send it to the client
|
|
const [toReponse, toCache] = body.tee();
|
|
|
|
streamToText(toCache).then(html => {
|
|
console.log('Caching', request.url);
|
|
cache.set(request.url, {
|
|
html: html.replace('Rendered Fresh', `Rendered from cache ${new Date().toISOString()}`),
|
|
date: new Date(),
|
|
});
|
|
});
|
|
|
|
const headers = new Headers(responseHeaders);
|
|
headers.set("Content-Type", "text/html");
|
|
const response = new Response(toReponse, {
|
|
headers,
|
|
status: didError ? 500 : responseStatusCode,
|
|
});
|
|
return response;
|
|
}
|