From c03299e96ca9b85f4b9b013c8f1271c7d2bc0835 Mon Sep 17 00:00:00 2001 From: Sem <931684+sembrestels@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:31:33 +0700 Subject: [PATCH] Use HydrateFallback with a modified entry.server.tsx --- apps/web/src/app/entry.client.tsx | 8 +----- apps/web/src/app/entry.server.tsx | 34 ++++++++++++++++++++++ apps/web/src/app/index.html | 7 +++++ apps/web/src/app/root.tsx | 48 ++++++++++++++++++++----------- 4 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 apps/web/src/app/entry.server.tsx create mode 100644 apps/web/src/app/index.html diff --git a/apps/web/src/app/entry.client.tsx b/apps/web/src/app/entry.client.tsx index f91c526..2d98100 100644 --- a/apps/web/src/app/entry.client.tsx +++ b/apps/web/src/app/entry.client.tsx @@ -1,16 +1,10 @@ -/** - * By default, Remix will handle hydrating your app on the client for you. - * 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` ✨ - * For more information, see https://remix.run/file-conventions/entry.client - */ - import { RemixBrowser } from "@remix-run/react"; import { StrictMode, startTransition } from "react"; import { hydrateRoot } from "react-dom/client"; startTransition(() => { hydrateRoot( - document, + document.querySelector("#app") as Element, , diff --git a/apps/web/src/app/entry.server.tsx b/apps/web/src/app/entry.server.tsx new file mode 100644 index 0000000..4c81b59 --- /dev/null +++ b/apps/web/src/app/entry.server.tsx @@ -0,0 +1,34 @@ +import fs from "node:fs"; +import path from "node:path"; + +import type { EntryContext } from "@remix-run/node"; +import { RemixServer } from "@remix-run/react"; +import { renderToString } from "react-dom/server"; + +import { MetaTags } from "./root"; + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + const shellHtml = fs + .readFileSync(path.join(process.cwd(), "src/app/index.html")) + .toString(); + + const appHtml = renderToString( + , + ); + + const metaHtml = renderToString(); + + const html = shellHtml + .replace("", metaHtml) + .replace("", appHtml); + + return new Response(html, { + headers: { "Content-Type": "text/html" }, + status: responseStatusCode, + }); +} diff --git a/apps/web/src/app/index.html b/apps/web/src/app/index.html new file mode 100644 index 0000000..ce0f9e0 --- /dev/null +++ b/apps/web/src/app/index.html @@ -0,0 +1,7 @@ + + + + +
+ + diff --git a/apps/web/src/app/root.tsx b/apps/web/src/app/root.tsx index d50b779..b4698e6 100644 --- a/apps/web/src/app/root.tsx +++ b/apps/web/src/app/root.tsx @@ -42,28 +42,42 @@ export function links() { ]; } -export const meta: MetaFunction = () => [ - { title: SITE_NAME }, - { name: "title", content: SITE_NAME }, - { name: "description", content: SITE_DESCRIPTION }, - { name: "theme-color", content: "#111827" }, - { name: "image", content: `${SITE_URL}/logo-bg.svg` }, - { property: "og:type", content: "website" }, - { property: "og:title", content: SITE_NAME }, - { property: "og:description", content: SITE_DESCRIPTION }, - { property: "og:url", content: SITE_URL }, - { property: "og:image", content: `${SITE_URL}/opengraph-image.webp` }, - { name: "twitter:card", content: "summary" }, - { name: "twitter:image", content: `${SITE_URL}/opengraph-image.webp` }, - { name: "twitter:site", content: SOCIAL_TWITTER }, -]; +export function MetaTags() { + return ( + <> + + + {SITE_NAME} + + + + + + + + + + + + + + ); +} + +export function HydrateFallback() { + return ( + <> +

Loading...

+ + + ); +} export default function App() { return ( - - +