ssr in prod (!!)
This commit is contained in:
23
packages/docs-new/build.ts
Normal file
23
packages/docs-new/build.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { resolve } from "node:path"
|
||||
import { build } from "vite"
|
||||
|
||||
await build({
|
||||
build: {
|
||||
outDir: "dist/client",
|
||||
lib: {
|
||||
entry: resolve("src/entry.client.tsx"),
|
||||
fileName: () => "entry.client.js",
|
||||
formats: ["es"],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await build({
|
||||
build: {
|
||||
ssr: resolve("src/entry.server.tsx"),
|
||||
outDir: "dist/server",
|
||||
rollupOptions: {
|
||||
output: { format: "es" },
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -3,19 +3,24 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "esmo src/server.tsx"
|
||||
"dev": "esmo src/server.ts",
|
||||
"build": "esmo build.ts",
|
||||
"start": "NODE_ENV=production esmo src/server.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.17.2",
|
||||
"reacord": "workspace:*",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/compression": "^1.7.2",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "*",
|
||||
"@types/react": "^17.0.38",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"@vitejs/plugin-react": "^1.1.3",
|
||||
"compression": "^1.7.4",
|
||||
"esno": "^0.13.0",
|
||||
"typescript": "^4.5.4",
|
||||
"vite": "^2.7.10"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from "react"
|
||||
import { render } from "react-dom"
|
||||
import { hydrate } from "react-dom"
|
||||
import { Root } from "./root"
|
||||
|
||||
render(<Root />, document)
|
||||
hydrate(<Root />, document)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as React from "react"
|
||||
import { Root } from "./root"
|
||||
|
||||
export async function render(url: string) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react"
|
||||
import { Counter } from "./counter"
|
||||
|
||||
export function Root() {
|
||||
@@ -10,7 +9,12 @@ export function Root() {
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="test description" />
|
||||
<title>Reacord</title>
|
||||
<script type="module" src="/src/entry.client.tsx" />
|
||||
<script
|
||||
type="module"
|
||||
src={
|
||||
import.meta.env.PROD ? "/entry.client.js" : "/src/entry.client.tsx"
|
||||
}
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<h1>hi</h1>
|
||||
|
||||
69
packages/docs-new/src/server.ts
Normal file
69
packages/docs-new/src/server.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import compression from "compression"
|
||||
import express, { Router } from "express"
|
||||
import { resolve } from "node:path"
|
||||
import { renderToString } from "react-dom/server"
|
||||
import { createServer as createViteServer } from "vite"
|
||||
import type * as entryModule from "./entry.server"
|
||||
|
||||
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 html = await vite.transformIndexHtml(
|
||||
url,
|
||||
renderToString(await render(url)),
|
||||
)
|
||||
|
||||
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")))
|
||||
.use("*", async (req, res) => {
|
||||
try {
|
||||
const { render }: typeof entryModule = await import(
|
||||
"../dist/server/entry.server"
|
||||
)
|
||||
|
||||
res
|
||||
.status(200)
|
||||
.set({ "Content-Type": "text/html" })
|
||||
.end(renderToString(await render(req.originalUrl)))
|
||||
} catch (error: any) {
|
||||
console.error(error)
|
||||
res.status(500).end(error.stack || error.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const app = express()
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
app.use(createProductionRouter())
|
||||
} else {
|
||||
app.use(await createDevelopmentRouter())
|
||||
}
|
||||
|
||||
const port = process.env.PORT || 3000
|
||||
app.listen(port, () => {
|
||||
console.log(`listening on http://localhost:${port}`)
|
||||
})
|
||||
@@ -1,35 +0,0 @@
|
||||
import express from "express"
|
||||
import { renderToStaticMarkup } from "react-dom/server"
|
||||
import { createServer as createViteServer } from "vite"
|
||||
import type * as entryModule from "./entry.server"
|
||||
|
||||
const vite = await createViteServer({
|
||||
server: { middlewareMode: "ssr" },
|
||||
})
|
||||
|
||||
const app = express()
|
||||
|
||||
app.use(vite.middlewares)
|
||||
|
||||
app.use("*", async (req, res) => {
|
||||
const url = req.originalUrl
|
||||
|
||||
try {
|
||||
const { render } = (await vite.ssrLoadModule(
|
||||
"/src/entry.server.tsx",
|
||||
)) as typeof entryModule
|
||||
|
||||
const content = renderToStaticMarkup(await render(url))
|
||||
const html = await vite.transformIndexHtml(url, content)
|
||||
res.status(200).set({ "Content-Type": "text/html" }).end(html)
|
||||
} catch (error: any) {
|
||||
vite.ssrFixStacktrace(error)
|
||||
console.error(error)
|
||||
res.status(500).end(error.message)
|
||||
}
|
||||
})
|
||||
|
||||
const port = process.env.PORT || 3000
|
||||
app.listen(port, () => {
|
||||
console.log(`listening on http://localhost:${port}`)
|
||||
})
|
||||
1
packages/docs-new/src/vite-env.d.ts
vendored
Normal file
1
packages/docs-new/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
Reference in New Issue
Block a user