diff --git a/.changeset/funny-suns-explain.md b/.changeset/funny-suns-explain.md new file mode 100644 index 0000000000..47418768b5 --- /dev/null +++ b/.changeset/funny-suns-explain.md @@ -0,0 +1,5 @@ +--- +"@react-router/dev": patch +--- + +Cancel aborts timeouts created in the default entry.server.tsx file diff --git a/contributors.yml b/contributors.yml index f5aa619629..7f89e40a00 100644 --- a/contributors.yml +++ b/contributors.yml @@ -342,3 +342,4 @@ - yuleicul - zeromask1337 - zheng-chuang +- remorses diff --git a/packages/react-router-dev/config/defaults/entry.server.node.tsx b/packages/react-router-dev/config/defaults/entry.server.node.tsx index d3bd0d84a3..76ef55c426 100644 --- a/packages/react-router-dev/config/defaults/entry.server.node.tsx +++ b/packages/react-router-dev/config/defaults/entry.server.node.tsx @@ -19,6 +19,7 @@ export default function handleRequest( return new Promise((resolve, reject) => { let shellRendered = false; let userAgent = request.headers.get("user-agent"); + let timeoutId: NodeJS.Timeout; // Ensure requests from bots and SPA Mode renders wait for all content to load before responding // https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation @@ -45,8 +46,10 @@ export default function handleRequest( ); pipe(body); + clearTimeout(timeoutId); }, onShellError(error: unknown) { + clearTimeout(timeoutId); reject(error); }, onError(error: unknown) { @@ -56,6 +59,7 @@ export default function handleRequest( // reject and get logged in handleDocumentRequest. if (shellRendered) { console.error(error); + clearTimeout(timeoutId); } }, } @@ -63,6 +67,6 @@ export default function handleRequest( // Abort the rendering stream after the `streamTimeout` so it has time to // flush down the rejected boundaries - setTimeout(abort, streamTimeout + 1000); + timeoutId = setTimeout(abort, streamTimeout + 1000); }); }