-
Notifications
You must be signed in to change notification settings - Fork 515
/
ssr.ts
73 lines (61 loc) · 2.03 KB
/
ssr.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { readFile, writeFile } from "node:fs/promises";
import { fdir } from "fdir";
import { BUILD_OUT_ROOT } from "../libs/env/index.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { renderHTML } from "../ssr/dist/main.js";
import { HydrationData } from "../libs/types/hydration.js";
import { chunks, formatDuration } from "./utils.js";
export function ssrDocument(context: HydrationData) {
return renderHTML(context);
}
interface SSROptions {
skipDocs?: boolean;
}
export async function ssrAllDocuments({
skipDocs: skipDocs = false,
}: SSROptions = {}) {
const files = await findDocuments({ skipDocs });
const start = Date.now();
const renderedFiles = [];
for (const chunk of chunks(files, 1000)) {
const out = await Promise.all(chunk.map(ssrSingleDocument).filter(Boolean));
renderedFiles.push(...out);
}
const end = Date.now();
const count = renderedFiles.length;
const seconds = (end - start) / 1000;
const took = formatDuration(seconds);
console.log(
`Rendered ${count.toLocaleString()} pages in ${took}, at a rate of ${(
count / seconds
).toFixed(1)} documents per second.`
);
}
async function findDocuments(options: Pick<SSROptions, "skipDocs">) {
const api = new fdir()
.withFullPaths()
.withErrors()
.exclude((dirName) => options.skipDocs && dirName === "docs")
.filter(
(filePath) =>
!filePath.endsWith("search-index.json") &&
(filePath.endsWith("index.json") || filePath.endsWith("404.json"))
)
.crawl(BUILD_OUT_ROOT);
const docs = await api.withPromise();
return docs;
}
async function ssrSingleDocument(file: string): Promise<string> {
const context: HydrationData = JSON.parse(await readFile(file, "utf-8"));
if (!context?.url) {
console.warn(
`WARNING: Skipped rendering HTML. Document is missing url: ${file}`
);
return null;
}
const html = renderHTML(context);
const outputFile = file.replace(/.json$/, ".html");
await writeFile(outputFile, html);
return outputFile;
}