From bfe12c9bcda3b1b92ec09abe5c5cc7a35a5a0c0c Mon Sep 17 00:00:00 2001 From: MapleLeaf <19603573+itsMapleLeaf@users.noreply.github.com> Date: Sun, 2 Jan 2022 17:10:29 -0600 Subject: [PATCH] use vite-plugin-ssr --- packages/docs-new/build.ts | 16 ---- packages/docs-new/index.html | 21 ---- packages/docs-new/package.json | 19 ++-- packages/docs-new/server.ts | 95 ++++++------------- ...ry.client.tsx => _default.page.client.tsx} | 16 ++-- .../docs-new/src/_default.page.server.tsx | 46 +++++++++ packages/docs-new/src/app.tsx | 35 +------ packages/docs-new/src/components/app-link.tsx | 10 +- .../src/components/guide-page-layout.tsx | 3 +- .../src/components/main-navigation.tsx | 5 +- packages/docs-new/src/data/main-links.tsx | 2 +- packages/docs-new/src/entry.server.tsx | 34 ------- packages/docs-new/src/html.ts | 36 ------- .../docs-new/src/pages/docs.page.route.tsx | 1 + packages/docs-new/src/pages/docs.page.tsx | 50 ++++++++++ .../{landing-page.tsx => index.page.tsx} | 11 ++- packages/docs-new/vite.config.ts | 2 + pnpm-lock.yaml | 43 ++++++++- 18 files changed, 203 insertions(+), 242 deletions(-) delete mode 100644 packages/docs-new/build.ts delete mode 100644 packages/docs-new/index.html rename packages/docs-new/src/{entry.client.tsx => _default.page.client.tsx} (50%) create mode 100644 packages/docs-new/src/_default.page.server.tsx delete mode 100644 packages/docs-new/src/entry.server.tsx delete mode 100644 packages/docs-new/src/html.ts create mode 100644 packages/docs-new/src/pages/docs.page.route.tsx create mode 100644 packages/docs-new/src/pages/docs.page.tsx rename packages/docs-new/src/pages/{landing-page.tsx => index.page.tsx} (87%) diff --git a/packages/docs-new/build.ts b/packages/docs-new/build.ts deleted file mode 100644 index 97a1ec5..0000000 --- a/packages/docs-new/build.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { resolve } from "node:path" -import { build } from "vite" - -await build({ - build: { outDir: "dist/client" }, -}) - -await build({ - build: { - ssr: resolve("src/entry.server.tsx"), - outDir: "dist/server", - rollupOptions: { - output: { format: "es" }, - }, - }, -}) diff --git a/packages/docs-new/index.html b/packages/docs-new/index.html deleted file mode 100644 index 6358701..0000000 --- a/packages/docs-new/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - -
- -
- - diff --git a/packages/docs-new/package.json b/packages/docs-new/package.json index 9bfcca1..171ad67 100644 --- a/packages/docs-new/package.json +++ b/packages/docs-new/package.json @@ -4,22 +4,23 @@ "private": true, "scripts": { "dev": "esmo server.ts", - "build": "esmo build.ts", + "build": "vite build && vite build --ssr", "start": "NODE_ENV=production esmo server.ts" }, "dependencies": { - "express": "^4.17.2", - "reacord": "workspace:*", - "react": "^18.0.0-rc.0", - "react-dom": "^18.0.0-rc.0", - "react-head": "^3.4.0", - "react-router": "^6.2.1", - "react-router-dom": "^6.2.1", "@heroicons/react": "^1.0.5", "@reach/rect": "^0.16.0", "clsx": "^1.1.1", + "express": "^4.17.2", "gray-matter": "^4.0.3", - "react-focus-on": "^3.5.4" + "reacord": "workspace:*", + "react": "^18.0.0-rc.0", + "react-dom": "^18.0.0-rc.0", + "react-focus-on": "^3.5.4", + "react-head": "^3.4.0", + "react-router": "^6.2.1", + "react-router-dom": "^6.2.1", + "vite-plugin-ssr": "^0.3.42" }, "devDependencies": { "@mapbox/rehype-prism": "^0.8.0", diff --git a/packages/docs-new/server.ts b/packages/docs-new/server.ts index 16df0ff..f40c9c2 100644 --- a/packages/docs-new/server.ts +++ b/packages/docs-new/server.ts @@ -1,76 +1,39 @@ -import compression from "compression" -import express, { Router } from "express" -import { readFile } from "node:fs/promises" -import { join, resolve } from "node:path" -import { createServer as createViteServer } from "vite" -import type * as entryModule from "./src/entry.server" +import express from "express" +import { dirname, join } from "node:path" +import { fileURLToPath } from "node:url" +import { createPageRenderer } from "vite-plugin-ssr" -async function createDevelopmentRouter() { - const vite = await createViteServer({ - server: { middlewareMode: "ssr" }, - }) - - return Router() - .use(vite.middlewares) - .use("*", async (req, res) => { - const url = req.originalUrl - - try { - const { render } = (await vite.ssrLoadModule( - "/src/entry.server.tsx", - )) as typeof entryModule - - const htmlTemplate = await readFile( - join(vite.config.root, "index.html"), - "utf8", - ) - - const html = await vite.transformIndexHtml( - url, - render(url, htmlTemplate), - ) - - res.status(200).set({ "Content-Type": "text/html" }).end(html) - } catch (error: any) { - vite.ssrFixStacktrace(error) - console.error(error) - res.status(500).end(error.stack || error.message) - } - }) -} - -function createProductionRouter() { - return Router() - .use(compression()) - .use(express.static(resolve("dist/client"), { index: false })) - .use("*", async (req, res) => { - try { - const { render }: typeof entryModule = await import( - "./dist/server/entry.server" - ) - - const htmlTemplate = await readFile("dist/client/index.html", "utf8") - - res - .status(200) - .set({ "Content-Type": "text/html" }) - .end(render(req.originalUrl, htmlTemplate)) - } catch (error: any) { - console.error(error) - res.status(500).end(error.stack || error.message) - } - }) -} +const isProduction = process.env.NODE_ENV === "production" +const root = dirname(fileURLToPath(import.meta.url)) const app = express() -if (process.env.NODE_ENV === "production") { - app.use(createProductionRouter()) +let viteDevServer +if (isProduction) { + app.use(express.static(join(root, "dist/client"))) } else { - app.use(await createDevelopmentRouter()) + const vite = await import("vite") + viteDevServer = await vite.createServer({ + root, + server: { middlewareMode: "ssr" }, + }) + app.use(viteDevServer.middlewares) } +const renderPage = createPageRenderer({ viteDevServer, isProduction, root }) +app.get("*", async (req, res, next) => { + const url = req.originalUrl + const pageContextInit = { + url, + } + const pageContext = await renderPage(pageContextInit) + const { httpResponse } = pageContext + if (!httpResponse) return next() + const { body, statusCode, contentType } = httpResponse + res.status(statusCode).type(contentType).send(body) +}) + const port = process.env.PORT || 3000 app.listen(port, () => { - console.log(`listening on http://localhost:${port}`) + console.info(`Server running at http://localhost:${port}`) }) diff --git a/packages/docs-new/src/entry.client.tsx b/packages/docs-new/src/_default.page.client.tsx similarity index 50% rename from packages/docs-new/src/entry.client.tsx rename to packages/docs-new/src/_default.page.client.tsx index b675088..38cbb6b 100644 --- a/packages/docs-new/src/entry.client.tsx +++ b/packages/docs-new/src/_default.page.client.tsx @@ -1,14 +1,18 @@ +import React from "react" import { createRoot } from "react-dom" import { HeadProvider } from "react-head" -import { BrowserRouter } from "react-router-dom" +import type { PageContextBuiltInClient } from "vite-plugin-ssr/client" +import { getPage } from "vite-plugin-ssr/client" import { App } from "./app" +const context = await getPage() + createRoot(document.querySelector("#app")!).render( - - - - - , + + + + + , ) declare module "react-dom" { diff --git a/packages/docs-new/src/_default.page.server.tsx b/packages/docs-new/src/_default.page.server.tsx new file mode 100644 index 0000000..9a06be5 --- /dev/null +++ b/packages/docs-new/src/_default.page.server.tsx @@ -0,0 +1,46 @@ +import React from "react" +import { renderToStaticMarkup, renderToString } from "react-dom/server.js" +import { HeadProvider } from "react-head" +import type { PageContextBuiltIn } from "vite-plugin-ssr" +import { dangerouslySkipEscape, escapeInject } from "vite-plugin-ssr" +import { App } from "./app" + +export const passToClient = ["routeParams"] + +export function render(context: PageContextBuiltIn) { + const headTags: React.ReactElement[] = [] + + const pageHtml = renderToString( + + + + + , + ) + + const documentHtml = escapeInject/* HTML */ ` + + + + + + + + + ${dangerouslySkipEscape(renderToStaticMarkup(<>{headTags}))} + + +
${dangerouslySkipEscape(pageHtml)}
+ + + ` + + return { documentHtml } +} diff --git a/packages/docs-new/src/app.tsx b/packages/docs-new/src/app.tsx index 5bf804a..2921b5d 100644 --- a/packages/docs-new/src/app.tsx +++ b/packages/docs-new/src/app.tsx @@ -1,41 +1,14 @@ import { description } from "reacord/package.json" -import { lazy, Suspense } from "react" import { Meta, Title } from "react-head" -import { Route, Routes } from "react-router-dom" -import { GuidePageLayout } from "./components/guide-page-layout" -import { LandingPage } from "./pages/landing-page" +import "tailwindcss/tailwind.css" +import "./styles/prism-theme.css" -export function App() { +export function App({ children }: { children: React.ReactNode }) { return ( <> Reacord - - } /> - }> - {docs.map(({ route, component: Component }) => ( - }> - - - } - /> - ))} - - + {children} ) } - -const docs = Object.entries(import.meta.glob("./docs/*.md")).map( - ([path, loadModule]) => ({ - route: path.replace("./docs/", "").replace(/\.md$/, ""), - component: lazy(async () => { - const m = await loadModule() - return { default: m.default || m } - }), - }), -) diff --git a/packages/docs-new/src/components/app-link.tsx b/packages/docs-new/src/components/app-link.tsx index 6045973..4e51980 100644 --- a/packages/docs-new/src/components/app-link.tsx +++ b/packages/docs-new/src/components/app-link.tsx @@ -1,8 +1,7 @@ -import { Link } from "react-router-dom" import { ExternalLink } from "./external-link" export type AppLinkProps = { - type: "router" | "internal" | "external" + type: "internal" | "external" label: React.ReactNode to: string className?: string @@ -10,13 +9,6 @@ export type AppLinkProps = { export function AppLink(props: AppLinkProps) { switch (props.type) { - case "router": - return ( - - {props.label} - - ) - case "internal": return ( diff --git a/packages/docs-new/src/components/guide-page-layout.tsx b/packages/docs-new/src/components/guide-page-layout.tsx index 217c048..d9c5cf4 100644 --- a/packages/docs-new/src/components/guide-page-layout.tsx +++ b/packages/docs-new/src/components/guide-page-layout.tsx @@ -1,5 +1,4 @@ import clsx from "clsx" -import { Outlet } from "react-router" import { guideLinks } from "../data/guide-links" import { useScrolled } from "../hooks/dom/use-scrolled" import { @@ -30,7 +29,7 @@ export function GuidePageLayout() {
- + {/* todo */}
diff --git a/packages/docs-new/src/components/main-navigation.tsx b/packages/docs-new/src/components/main-navigation.tsx index 31e94db..790c5b0 100644 --- a/packages/docs-new/src/components/main-navigation.tsx +++ b/packages/docs-new/src/components/main-navigation.tsx @@ -1,4 +1,3 @@ -import { Link } from "react-router-dom" import { AppLink } from "../components/app-link" import { guideLinks } from "../data/guide-links" import { mainLinks } from "../data/main-links" @@ -8,9 +7,9 @@ import { PopoverMenu } from "./popover-menu" export function MainNavigation() { return (