Skip to content

Commit e246433

Browse files
committed
feat: [advanced]ssg 연결
1 parent ea8e413 commit e246433

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

packages/react/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"build:client-for-ssg": "rm -rf ../../dist/react && vite build --outDir ../../dist/react",
1414
"build:server": "vite build --outDir ./dist/react-ssr --ssr src/main-server.tsx",
1515
"build:without-ssg": "pnpm run build:client && npm run build:server",
16-
"build:ssg": "pnpm run build:client-for-ssg && node static-site-generate.js",
16+
"build:ssg": "pnpm run build:client-for-ssg && NODE_ENV=production node static-site-generate.js",
1717
"build": "npm run build:client && npm run build:server && npm run build:ssg",
1818
"preview:csr": "vite preview --outDir ./dist/react --port 4175",
1919
"preview:csr-with-build": "pnpm run build:client && pnpm run preview:csr",
Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,54 @@
1-
import { renderToString } from "react-dom/server";
2-
import { createElement } from "react";
31
import fs from "fs";
2+
import path from "node:path";
3+
import { createServer } from "vite";
44

5-
async function generateStaticSite() {
6-
// HTML 템플릿 읽기
7-
const template = fs.readFileSync("../../dist/react/index.html", "utf-8");
5+
const vite = await createServer({
6+
server: { middlewareMode: true },
7+
appType: "custom",
8+
});
89

9-
// 어플리케이션 렌더링하기
10-
const appHtml = renderToString(createElement("div", null, "안녕하세요"));
10+
const { mswServer } = await vite.ssrLoadModule("./src/mocks/node.ts");
11+
mswServer.listen({
12+
onUnhandledRequest: "bypass",
13+
});
1114

12-
// 결과 HTML 생성하기
13-
const result = template.replace("<!--app-html-->", appHtml);
14-
fs.writeFileSync("../../dist/react/index.html", result);
15+
const { render } = await vite.ssrLoadModule("./src/main-server.tsx");
16+
17+
const joinDist = (...pathnames) => path.join("../../dist/react", ...pathnames);
18+
19+
const template = fs.readFileSync(joinDist("/index.html"), "utf-8");
20+
21+
async function generateStaticSite(pathname) {
22+
const fullPathname = pathname.endsWith(".html") ? joinDist(pathname) : joinDist(pathname, "/index.html");
23+
const parsedPath = path.parse(fullPathname);
24+
25+
const rendered = await render(pathname, {});
26+
27+
const html = template
28+
.replace(`<!--app-head-->`, rendered.head ?? "")
29+
.replace(`<!--app-html-->`, rendered.html ?? "")
30+
.replace(
31+
`<!-- app-data -->`,
32+
`<script>window.__INITIAL_DATA__ = ${JSON.stringify(rendered.__INITIAL_DATA__)};</script>`,
33+
);
34+
35+
if (!fs.existsSync(parsedPath.dir)) {
36+
fs.mkdirSync(parsedPath.dir, { recursive: true });
37+
}
38+
39+
fs.writeFileSync(fullPathname, html);
1540
}
1641

17-
// 실행
18-
generateStaticSite();
42+
// 404 생성
43+
await generateStaticSite("/404.html");
44+
45+
// 홈 생성
46+
await generateStaticSite("/");
47+
48+
// 상세페이지 생성
49+
const { getProducts } = await vite.ssrLoadModule("./src/api/productApi.ts");
50+
const { products } = await getProducts();
51+
await Promise.all(products.map(async ({ productId }) => await generateStaticSite(`/product/${productId}/`)));
52+
53+
mswServer.close();
54+
vite.close();

0 commit comments

Comments
 (0)