Layout scaffolding for Web apps.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

entry.server.tsx 2.9 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /**
  2. * By default, Remix will handle generating the HTTP Response for you.
  3. * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
  4. * For more information, see https://remix.run/docs/en/main/file-conventions/entry.server
  5. */
  6. import { PassThrough } from "node:stream";
  7. import type { EntryContext } from "@remix-run/node";
  8. import { Response } from "@remix-run/node";
  9. import { RemixServer } from "@remix-run/react";
  10. import isbot from "isbot";
  11. import { renderToPipeableStream } from "react-dom/server";
  12. const ABORT_DELAY = 5_000;
  13. export default function handleRequest(
  14. request: Request,
  15. responseStatusCode: number,
  16. responseHeaders: Headers,
  17. remixContext: EntryContext
  18. ) {
  19. return isbot(request.headers.get("user-agent"))
  20. ? handleBotRequest(
  21. request,
  22. responseStatusCode,
  23. responseHeaders,
  24. remixContext
  25. )
  26. : handleBrowserRequest(
  27. request,
  28. responseStatusCode,
  29. responseHeaders,
  30. remixContext
  31. );
  32. }
  33. function handleBotRequest(
  34. request: Request,
  35. responseStatusCode: number,
  36. responseHeaders: Headers,
  37. remixContext: EntryContext
  38. ) {
  39. return new Promise((resolve, reject) => {
  40. const { pipe, abort } = renderToPipeableStream(
  41. <RemixServer
  42. context={remixContext}
  43. url={request.url}
  44. abortDelay={ABORT_DELAY}
  45. />,
  46. {
  47. onAllReady() {
  48. const body = new PassThrough();
  49. responseHeaders.set("Content-Type", "text/html");
  50. resolve(
  51. new Response(body, {
  52. headers: responseHeaders,
  53. status: responseStatusCode,
  54. })
  55. );
  56. pipe(body);
  57. },
  58. onShellError(error: unknown) {
  59. reject(error);
  60. },
  61. onError(error: unknown) {
  62. responseStatusCode = 500;
  63. console.error(error);
  64. },
  65. }
  66. );
  67. setTimeout(abort, ABORT_DELAY);
  68. });
  69. }
  70. function handleBrowserRequest(
  71. request: Request,
  72. responseStatusCode: number,
  73. responseHeaders: Headers,
  74. remixContext: EntryContext
  75. ) {
  76. return new Promise((resolve, reject) => {
  77. const { pipe, abort } = renderToPipeableStream(
  78. <RemixServer
  79. context={remixContext}
  80. url={request.url}
  81. abortDelay={ABORT_DELAY}
  82. />,
  83. {
  84. onShellReady() {
  85. const body = new PassThrough();
  86. responseHeaders.set("Content-Type", "text/html");
  87. resolve(
  88. new Response(body, {
  89. headers: responseHeaders,
  90. status: responseStatusCode,
  91. })
  92. );
  93. pipe(body);
  94. },
  95. onShellError(error: unknown) {
  96. reject(error);
  97. },
  98. onError(error: unknown) {
  99. console.error(error);
  100. responseStatusCode = 500;
  101. },
  102. }
  103. );
  104. setTimeout(abort, ABORT_DELAY);
  105. });
  106. }