Skip to content

Commit f703ccc

Browse files
committed
ssg
1 parent 6308b2a commit f703ccc

File tree

3 files changed

+112
-11
lines changed

3 files changed

+112
-11
lines changed
Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
---
2-
title: "What is an RSC?"
2+
title: "Client-Side React"
33
---
44

5-
# TODO: split this page up into multiple page. add code examples for SSG and SSR
6-
75
> 💡 This course assumes you have taken or at least understand the concepts in [The Complete Intro to React v9][v9]. If you don't, please go back and take that one first, this will make a lot more sense.
86
97
React Server Components (which I will now abbreviate as RSC) are a concept that have been teased for a few years before landing in stable React in early 2025 when React 19 was officially realeased. No doubt they are a very interesting piece of technology and offer a lot of upside. They have some interesting trade-offs and we'll talk about them, but don't be quick to paint them as bad as some have, and definitely don't use them _everywhere_ either, they have a time and place.
@@ -18,13 +16,7 @@ This is how we've written React for a very long time (10+ years now) and will co
1816

1917
Brian's (not-so) 🔥 Take: this is the default way you should write React. Everything is a contextual performance enhancement, and should only be reached for when: 1. the performance enhancement actually meaningfully helps (it frequently doesn't) and 2. you actually have a need for the performance enhancement (you frequently don't). This style of rendering yields the simplest apps that are easiest to write, easiest to maintain, and easiest to debug.
2018

21-
## Static-Site Generation (SSG)
22-
23-
> Fun fact: this very website is rendered via SSG with Next.js! [See the code here][code]
24-
25-
Static Site generation allows you to use React to generate a fully static site. This is perfect for sites like blogs or course materials (like this site) where it's just a bunch of static pages that don't need the interactivity of React. It's enough to render this out once - it doesn't need the interactivity. The result is the end user is just shipped fully rendered flat HTML files - it doesn't need a server or client to do it. The developer can still add some interactivity via React, but minimally so.
26-
27-
This is just useful for static content. I love it because it helps me ship these courses faster, but it's not a good fit for anything with much more than basic interactivity.
19+
# TODO Move these two to their own pages
2820

2921
## Server-Side Rendered (SSR)
3022

@@ -35,4 +27,3 @@ SSR is a double-edged sword. It can be a huge help, saving slow devices from hav
3527
## React Server Components
3628

3729
[v9]: https://react-v9.holt.courses
38-
[code]: https://github.com/btholt/intermediate-react-v6/
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
> Fun fact: this very website is rendered via SSG with Next.js! [See the code here][code]
2+
3+
Static Site generation allows you to use React to generate a fully static site. This is perfect for sites like blogs or course materials (like this site) where it's just a bunch of static pages that don't need the interactivity of React. It's enough to render this out once - it doesn't need the interactivity. The result is the end user is just shipped fully rendered flat HTML files - it doesn't need a server or client to do it. The developer can still add some interactivity via React, but minimally so.
4+
5+
This is just useful for static content. I love it because it helps me ship these courses faster, but it's not a good fit for anything with much more than basic interactivity.
6+
7+
## Let's Build It
8+
9+
This is going to be almost insultingly easy but I want you to see that at its core, they frameworks are mostly doing dev experience work and tools around the actual static site generation and that React itself is doing the heavy lifting.
10+
11+
Create a new folder. In that folder, run
12+
13+
```bash
14+
npm init -y
15+
npm i react react-dom
16+
```
17+
18+
In your package.json, add `"type": "module"` as a top level item. Also add `"build": "node ./build.js"` to your scripts.
19+
20+
> 💡 We're going to do this with vanilla JS and not JSX so we don't need to bring in Babel/Vite/Webpack/whatever. You could absolutely bring in those if you wanted to, I'm just trying to keep these examples as simple as possible.
21+
22+
Create an App.js file, put in there
23+
24+
```javascript
25+
import { createElement as h } from "react";
26+
27+
function App() {
28+
return h(
29+
"div",
30+
null,
31+
h("h1", null, "Hello Frontend Masters"),
32+
h("p", null, "This is SSG")
33+
);
34+
}
35+
36+
export default App;
37+
```
38+
39+
Now create a build.js and put
40+
41+
```javascript
42+
import { renderToString } from "react-dom/server";
43+
import { createElement as h } from "react";
44+
import {
45+
readFileSync,
46+
writeFileSync,
47+
existsSync,
48+
mkdirSync,
49+
readdirSync,
50+
unlinkSync,
51+
} from "node:fs";
52+
import { fileURLToPath } from "node:url";
53+
import path, { dirname } from "node:path";
54+
import App from "./App.js";
55+
56+
const __filename = fileURLToPath(import.meta.url);
57+
const __dirname = dirname(__filename);
58+
const distPath = path.join(__dirname, "dist");
59+
60+
const shell = readFileSync(path.join(__dirname, "index.html"), "utf8");
61+
62+
const app = renderToString(h(App));
63+
const html = shell.replace("<!--ROOT-->", app);
64+
65+
// Create dist folder if it doesn't exist
66+
if (!existsSync(distPath)) {
67+
mkdirSync(distPath);
68+
} else {
69+
// Delete all files in dist folder if it exists
70+
const files = readdirSync(distPath);
71+
for (const file of files) {
72+
unlinkSync(path.join(distPath, file));
73+
}
74+
}
75+
76+
writeFileSync(path.join(distPath, "index.html"), html);
77+
```
78+
79+
- Most of the code is making sure the dist folder exists, and if it does, is empty
80+
- We just take our App, render it to string, and stick it in the HTML shell
81+
- You actually _could_ just have React render everything, `<html>`, `<body>` and all.
82+
- We didn't include any CSS nor JS, but obviously you could.
83+
- For mild amounts of interactivity, you could include JS file with the React run time and hydrate the app, but we don't need to.
84+
85+
This generates one page. You could have it generate many pages any number of ways. We could write a `routes.js` file that defines a route and its route component and then have build.js loop over that. We could use `react-router` or something like and then make our build.js use those routes to generate route. Any of these are viable.
86+
87+
## Okay but just use Astro, Next.js, Gatsby, etc.
88+
89+
I wanted you to see how simple this is, but in reality I can't fathom why you'd do this. You are just `npm create astro@latest` from a full-featured framework that is optimized around making static content sites and I can't see why you wouldn't do that. This site is built on Next.js because it's the one I knew the best but if I were to rebuild my course builder website I'd use Astro.
90+
91+
## SSG with Next.js
92+
93+
This site is entirely SSG'd. In general you will never directly write SSG code yourself; you will rely on a framework to do it for you. I would say the two primary ways to do this are either using [Next.js's export mode][export] (which is what this site does) or using [Astro][astro]. Both are great, choose your favorite.
94+
95+
Let's dive in a second on how this course gets built.
96+
97+
- [Here's the link to this page's markdown file][md]
98+
- [Here's the link to this site's Next.js config][config]
99+
- [Here's the link to this page's built HTML][html]
100+
- [Here's the link to the entire site's built-out HTML][site-html]
101+
102+
Using this toolkit, I'm able to use React to write the wrappers of the pages of the course, write all the content in Markdown, and get all sorts of developer experience tools, SEO tools, and other tools that help make it easy for Frontend Masters to film these videos. I could write raw HTML or a Notion doc or something, but there's a ton of value being realized here by using Next.js
103+
104+
[code]: https://github.com/btholt/intermediate-react-v6/
105+
[export]: https://nextjs.org/docs/pages/building-your-application/deploying/static-exports
106+
[astro]: https://astro.build/
107+
[md]: https://github.com/btholt/intermediate-react-v6/blob/main/lessons/02-react-server-components/B-static-site-generation.md
108+
[config]: https://github.com/btholt/intermediate-react-v6/blob/main/next.config.js#L9
109+
[html]: https://github.com/btholt/intermediate-react-v6/blob/gh-pages/lessons/react-server-components/static-site-generation.html
110+
[site-html]: https://github.com/btholt/intermediate-react-v6/tree/gh-pages
File renamed without changes.

0 commit comments

Comments
 (0)