|
1
|
import express, { type Express } from "express"; |
|
2
|
import fs from "fs"; |
|
3
|
import path from "path"; |
|
4
|
import { createServer as createViteServer, createLogger } from "vite"; |
|
5
|
import { type Server } from "http"; |
|
6
|
import viteConfig from "../vite.config"; |
|
7
|
import { nanoid } from "nanoid"; |
|
8
|
|
|
9
|
const viteLogger = createLogger(); |
|
10
|
|
|
11
|
export function log(message: string, source = "express") { |
|
12
|
const formattedTime = new Date().toLocaleTimeString("en-US", { |
|
13
|
hour: "numeric", |
|
14
|
minute: "2-digit", |
|
15
|
second: "2-digit", |
|
16
|
hour12: true, |
|
17
|
}); |
|
18
|
|
|
19
|
console.log(`${formattedTime} [${source}] ${message}`); |
|
20
|
} |
|
21
|
|
|
22
|
export async function setupVite(app: Express, server: Server) { |
|
23
|
const serverOptions = { |
|
24
|
middlewareMode: true, |
|
25
|
hmr: { server }, |
|
26
|
allowedHosts: true as const, |
|
27
|
}; |
|
28
|
|
|
29
|
const vite = await createViteServer({ |
|
30
|
...viteConfig, |
|
31
|
configFile: false, |
|
32
|
customLogger: { |
|
33
|
...viteLogger, |
|
34
|
error: (msg, options) => { |
|
35
|
viteLogger.error(msg, options); |
|
36
|
process.exit(1); |
|
37
|
}, |
|
38
|
}, |
|
39
|
server: serverOptions, |
|
40
|
appType: "custom", |
|
41
|
}); |
|
42
|
|
|
43
|
app.use(vite.middlewares); |
|
44
|
app.use("*", async (req, res, next) => { |
|
45
|
const url = req.originalUrl; |
|
46
|
|
|
47
|
try { |
|
48
|
const clientTemplate = path.resolve( |
|
49
|
import.meta.dirname, |
|
50
|
"..", |
|
51
|
"client", |
|
52
|
"index.html", |
|
53
|
); |
|
54
|
|
|
55
|
// always reload the index.html file from disk incase it changes |
|
56
|
let template = await fs.promises.readFile(clientTemplate, "utf-8"); |
|
57
|
template = template.replace( |
|
58
|
`src="/src/main.tsx"`, |
|
59
|
`src="/src/main.tsx?v=${nanoid()}"`, |
|
60
|
); |
|
61
|
const page = await vite.transformIndexHtml(url, template); |
|
62
|
res.status(200).set({ "Content-Type": "text/html" }).end(page); |
|
63
|
} catch (e) { |
|
64
|
vite.ssrFixStacktrace(e as Error); |
|
65
|
next(e); |
|
66
|
} |
|
67
|
}); |
|
68
|
} |
|
69
|
|
|
70
|
export function serveStatic(app: Express) { |
|
71
|
const distPath = path.resolve(import.meta.dirname, "public"); |
|
72
|
|
|
73
|
if (!fs.existsSync(distPath)) { |
|
74
|
throw new Error( |
|
75
|
`Could not find the build directory: ${distPath}, make sure to build the client first`, |
|
76
|
); |
|
77
|
} |
|
78
|
|
|
79
|
app.use(express.static(distPath)); |
|
80
|
|
|
81
|
// fall through to index.html if the file doesn't exist |
|
82
|
app.use("*", (_req, res) => { |
|
83
|
res.sendFile(path.resolve(distPath, "index.html")); |
|
84
|
}); |
|
85
|
} |