From 18308a22879dc9143a03bcbe53cf0c5e8e49ee1f Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 27 Jul 2024 01:17:37 +0900 Subject: remix --- frontend/app/entry.client.tsx | 12 ++++ frontend/app/entry.server.tsx | 124 +++++++++++++++++++++++++++++++++++++++++ frontend/app/root.tsx | 35 ++++++++++++ frontend/app/routes/_index.tsx | 9 +++ frontend/app/tailwind.css | 3 + 5 files changed, 183 insertions(+) create mode 100644 frontend/app/entry.client.tsx create mode 100644 frontend/app/entry.server.tsx create mode 100644 frontend/app/root.tsx create mode 100644 frontend/app/routes/_index.tsx create mode 100644 frontend/app/tailwind.css (limited to 'frontend/app') diff --git a/frontend/app/entry.client.tsx b/frontend/app/entry.client.tsx new file mode 100644 index 0000000..442da4f --- /dev/null +++ b/frontend/app/entry.client.tsx @@ -0,0 +1,12 @@ +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +startTransition(() => { + hydrateRoot( + document, + + + , + ); +}); diff --git a/frontend/app/entry.server.tsx b/frontend/app/entry.server.tsx new file mode 100644 index 0000000..77b6f15 --- /dev/null +++ b/frontend/app/entry.server.tsx @@ -0,0 +1,124 @@ +import { PassThrough } from "node:stream"; + +import type { EntryContext } from "@remix-run/node"; +import { createReadableStreamFromReadable } from "@remix-run/node"; +import { RemixServer } from "@remix-run/react"; +import { isbot } from "isbot"; +import { renderToPipeableStream } from "react-dom/server"; + +const ABORT_DELAY = 5_000; + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return isbot(request.headers.get("user-agent") || "") + ? handleBotRequest( + request, + responseStatusCode, + responseHeaders, + remixContext, + ) + : handleBrowserRequest( + request, + responseStatusCode, + responseHeaders, + remixContext, + ); +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onAllReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + if (shellRendered) { + console.error(error); + } + }, + }, + ); + + setTimeout(abort, ABORT_DELAY); + }); +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + if (shellRendered) { + console.error(error); + } + }, + }, + ); + + setTimeout(abort, ABORT_DELAY); + }); +} diff --git a/frontend/app/root.tsx b/frontend/app/root.tsx new file mode 100644 index 0000000..9768f45 --- /dev/null +++ b/frontend/app/root.tsx @@ -0,0 +1,35 @@ +import type { LinksFunction } from "@remix-run/node"; +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, +} from "@remix-run/react"; +import "./tailwind.css"; + +export const links: LinksFunction = () => { + return [{ rel: "icon", href: "/favicon.svg" }]; +}; + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + {children} + + + + + ); +} + +export default function App() { + return ; +} diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx new file mode 100644 index 0000000..f39c7eb --- /dev/null +++ b/frontend/app/routes/_index.tsx @@ -0,0 +1,9 @@ +import type { MetaFunction } from "@remix-run/node"; + +export const meta: MetaFunction = () => { + return [{ title: "Albatross.swift" }]; +}; + +export default function Index() { + return

iOSDC 2024 Albatross.swift

; +} diff --git a/frontend/app/tailwind.css b/frontend/app/tailwind.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/frontend/app/tailwind.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; -- cgit v1.2.3-70-g09d2