Repository navigation
Expand file tree
/
Copy pathprerender.js
More file actions
111 lines (77 loc) · 2.73 KB
/
Copy pathprerender.js
File metadata and controls
111 lines (77 loc) · 2.73 KB
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import fs from "node:fs";
import path from "node:path";
import {fileURLToPath} from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const toAbsolute = (p) => path.resolve(__dirname, p);
const template = fs.readFileSync(toAbsolute("dist/client/index.html"), "utf8");
const {render} = await import("./dist/server/EntryServer.js");
const routesToPrerender = ["/", "/aefaq", "/prfaq", "/psfaq", "/rules", "/links", "/404"];
function extractMetadata(html, helmet) {
if (helmet) {
return {
headTags: `${helmet.meta.toString()}${helmet.link.toString()}`,
pageHtml: html,
titleTag: helmet.title.toString(),
};
}
let pageHtml = html;
let titleTag = "";
const titleMatch = pageHtml.match(/<title>([^<]*)<\/title>/);
if (titleMatch) {
titleTag = titleMatch[0];
pageHtml = pageHtml.replace(titleTag, "");
}
const allMeta = pageHtml.match(/<meta\b[^>]*\/?>/gi) || [];
const metaTags = allMeta.filter(
(tag) => tag.includes("name=") || tag.includes("property=")
);
const allLinks = pageHtml.match(/<link\b[^>]*\/?>/gi) || [];
const linkTags = allLinks.filter((tag) => tag.includes('rel="icon"'));
const headTags = [...metaTags, ...linkTags].join("");
for (const tag of [...metaTags, ...linkTags]) {
pageHtml = pageHtml.replace(tag, "");
}
return {
headTags,
pageHtml,
titleTag,
};
}
function applyPageTransforms(html, url) {
let transformed = html;
if (url.endsWith("404")) {
transformed = transformed.replace(
'<meta name="prerender-status-code" content="200">',
'<meta name="prerender-status-code" content="404">'
);
}
if (["/aefaq", "/prfaq", "/psfaq"].includes(url)) {
transformed = transformed.replaceAll("<details", "<details open");
}
return transformed;
}
(async () => {
for (const url of routesToPrerender) {
const context = {};
const {html} = await render(url, context);
const {headTags, pageHtml, titleTag} = extractMetadata(html, context.helmet);
let htmlWithMeta = template;
if (titleTag) {
htmlWithMeta = htmlWithMeta.replace(/<title>.*<\/title>/, titleTag);
}
if (headTags) {
htmlWithMeta = htmlWithMeta.replace("</head>", `${headTags}</head>`);
}
htmlWithMeta = htmlWithMeta.replace("<!--app-html-->", pageHtml);
htmlWithMeta = applyPageTransforms(htmlWithMeta, url);
const filePath = toAbsolute(
url === "/" ? "dist/client/index.html" : `dist/client${url}.html`
);
const dirPath = path.dirname(filePath);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, {recursive: true});
}
fs.writeFileSync(filePath, htmlWithMeta);
console.log(`prerendered: ${url} to ${path.relative(__dirname, filePath)}`);
}
})();