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",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "esmo src/server.tsx"
|
"dev": "esmo src/server.ts",
|
||||||
|
"build": "esmo build.ts",
|
||||||
|
"start": "NODE_ENV=production esmo src/server.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.17.2",
|
"express": "^4.17.2",
|
||||||
|
"reacord": "workspace:*",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^17.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/compression": "^1.7.2",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
"@vitejs/plugin-react": "^1.1.3",
|
"@vitejs/plugin-react": "^1.1.3",
|
||||||
|
"compression": "^1.7.4",
|
||||||
"esno": "^0.13.0",
|
"esno": "^0.13.0",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
"vite": "^2.7.10"
|
"vite": "^2.7.10"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as React from "react"
|
import { hydrate } from "react-dom"
|
||||||
import { render } from "react-dom"
|
|
||||||
import { Root } from "./root"
|
import { Root } from "./root"
|
||||||
|
|
||||||
render(<Root />, document)
|
hydrate(<Root />, document)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as React from "react"
|
|
||||||
import { Root } from "./root"
|
import { Root } from "./root"
|
||||||
|
|
||||||
export async function render(url: string) {
|
export async function render(url: string) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from "react"
|
|
||||||
import { Counter } from "./counter"
|
import { Counter } from "./counter"
|
||||||
|
|
||||||
export function Root() {
|
export function Root() {
|
||||||
@@ -10,7 +9,12 @@ export function Root() {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="description" content="test description" />
|
<meta name="description" content="test description" />
|
||||||
<title>Reacord</title>
|
<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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>hi</h1>
|
<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" />
|
||||||
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@@ -112,27 +112,33 @@ importers:
|
|||||||
|
|
||||||
packages/docs-new:
|
packages/docs-new:
|
||||||
specifiers:
|
specifiers:
|
||||||
|
'@types/compression': ^1.7.2
|
||||||
'@types/express': ^4.17.13
|
'@types/express': ^4.17.13
|
||||||
'@types/node': '*'
|
'@types/node': '*'
|
||||||
'@types/react': ^17.0.38
|
'@types/react': ^17.0.38
|
||||||
'@types/react-dom': ^17.0.9
|
'@types/react-dom': ^17.0.9
|
||||||
'@vitejs/plugin-react': ^1.1.3
|
'@vitejs/plugin-react': ^1.1.3
|
||||||
|
compression: ^1.7.4
|
||||||
esno: ^0.13.0
|
esno: ^0.13.0
|
||||||
express: ^4.17.2
|
express: ^4.17.2
|
||||||
|
reacord: workspace:*
|
||||||
react: ^17.0.2
|
react: ^17.0.2
|
||||||
react-dom: ^17.0.2
|
react-dom: ^17.0.2
|
||||||
typescript: ^4.5.4
|
typescript: ^4.5.4
|
||||||
vite: ^2.7.10
|
vite: ^2.7.10
|
||||||
dependencies:
|
dependencies:
|
||||||
express: 4.17.2
|
express: 4.17.2
|
||||||
|
reacord: link:../reacord
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/compression': 1.7.2
|
||||||
'@types/express': 4.17.13
|
'@types/express': 4.17.13
|
||||||
'@types/node': 17.0.5
|
'@types/node': 17.0.5
|
||||||
'@types/react': 17.0.38
|
'@types/react': 17.0.38
|
||||||
'@types/react-dom': 17.0.11
|
'@types/react-dom': 17.0.11
|
||||||
'@vitejs/plugin-react': 1.1.3
|
'@vitejs/plugin-react': 1.1.3
|
||||||
|
compression: 1.7.4
|
||||||
esno: 0.13.0_typescript@4.5.4
|
esno: 0.13.0_typescript@4.5.4
|
||||||
typescript: 4.5.4
|
typescript: 4.5.4
|
||||||
vite: 2.7.10
|
vite: 2.7.10
|
||||||
@@ -1262,6 +1268,12 @@ packages:
|
|||||||
'@types/node': 17.0.5
|
'@types/node': 17.0.5
|
||||||
'@types/responselike': 1.0.0
|
'@types/responselike': 1.0.0
|
||||||
|
|
||||||
|
/@types/compression/1.7.2:
|
||||||
|
resolution: {integrity: sha512-lwEL4M/uAGWngWFLSG87ZDr2kLrbuR8p7X+QZB1OQlT+qkHsCPDVFnHPyXf4Vyl4yDDorNY+mAhosxkCvppatg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 4.17.13
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/connect/3.4.35:
|
/@types/connect/3.4.35:
|
||||||
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
|
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1694,7 +1706,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mime-types: 2.1.34
|
mime-types: 2.1.34
|
||||||
negotiator: 0.6.2
|
negotiator: 0.6.2
|
||||||
dev: false
|
|
||||||
|
|
||||||
/acorn-globals/6.0.0:
|
/acorn-globals/6.0.0:
|
||||||
resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==}
|
resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==}
|
||||||
@@ -2296,7 +2307,6 @@ packages:
|
|||||||
/bytes/3.0.0:
|
/bytes/3.0.0:
|
||||||
resolution: {integrity: sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=}
|
resolution: {integrity: sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/bytes/3.1.1:
|
/bytes/3.1.1:
|
||||||
resolution: {integrity: sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==}
|
resolution: {integrity: sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==}
|
||||||
@@ -2649,7 +2659,6 @@ packages:
|
|||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db: 1.51.0
|
mime-db: 1.51.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/compression/1.7.4:
|
/compression/1.7.4:
|
||||||
resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==}
|
resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==}
|
||||||
@@ -2662,7 +2671,6 @@ packages:
|
|||||||
on-headers: 1.0.2
|
on-headers: 1.0.2
|
||||||
safe-buffer: 5.1.2
|
safe-buffer: 5.1.2
|
||||||
vary: 1.1.2
|
vary: 1.1.2
|
||||||
dev: false
|
|
||||||
|
|
||||||
/concat-map/0.0.1:
|
/concat-map/0.0.1:
|
||||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||||
@@ -6656,7 +6664,6 @@ packages:
|
|||||||
/negotiator/0.6.2:
|
/negotiator/0.6.2:
|
||||||
resolution: {integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==}
|
resolution: {integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/nested-error-stacks/2.1.0:
|
/nested-error-stacks/2.1.0:
|
||||||
resolution: {integrity: sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==}
|
resolution: {integrity: sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==}
|
||||||
@@ -6863,7 +6870,6 @@ packages:
|
|||||||
/on-headers/1.0.2:
|
/on-headers/1.0.2:
|
||||||
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
|
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/once/1.4.0:
|
/once/1.4.0:
|
||||||
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
|
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
|
||||||
@@ -9045,7 +9051,6 @@ packages:
|
|||||||
/vary/1.1.2:
|
/vary/1.1.2:
|
||||||
resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=}
|
resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/vfile-location/4.0.1:
|
/vfile-location/4.0.1:
|
||||||
resolution: {integrity: sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==}
|
resolution: {integrity: sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==}
|
||||||
|
|||||||
Reference in New Issue
Block a user