mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-04-04 23:03:45 -04:00
Add Next.js.md
This commit is contained in:
389
docs/Next.js.md
Normal file
389
docs/Next.js.md
Normal file
@@ -0,0 +1,389 @@
|
||||
### Terminology
|
||||
|
||||
- SSR: server-side rendering
|
||||
- SSG
|
||||
- ISR
|
||||
- Edge
|
||||
- Lambda
|
||||
|
||||
### DOM
|
||||
|
||||
Document Object Model: The in-browser tree of HTML elements representing the page.
|
||||
|
||||
### Client
|
||||
|
||||
The user's environment, the browser. The front-end is the code running in that environment.
|
||||
On Compass, it can be any browser (Chrome, Firefox, etc.).
|
||||
|
||||
### Server
|
||||
|
||||
Any remote infrastructure, i.e., not running in the user's environment / OS. The back-end is the code that runs in that environment.
|
||||
On Compass, there are two servers:
|
||||
- Web server: hosted on Vercel at `compassmeet.com`, which mostly provides the web pages to the client. That's the server we are talking about in the rest of the document.
|
||||
- Core server: hosted on Google Cloud at `api.compassmeet.com`, a server with more resources and permissions to update the database. It's in charge of any operation related to non-web data (i.e., no HTML or CSS) such as accounts, profiles, messages, and votes.
|
||||
|
||||
---
|
||||
### React
|
||||
|
||||
React is a client-side UI library.
|
||||
Its core job: create and update a **virtual DOM**, then reconcile that with the **real DOM** in the browser.
|
||||
React itself **does not** define routing, data fetching conventions, or server rendering (it allows it, but doesn’t provide a full system).
|
||||
|
||||
**Key behavior:**
|
||||
|
||||
- React components run on the **client** by default.
|
||||
- React can be rendered on the **server** (via frameworks like Next.js), but this requires additional tooling.
|
||||
- React uses a Virtual DOM to compute minimal changes, then applies them to the real DOM.
|
||||
|
||||
---
|
||||
### Hydration
|
||||
|
||||
When a framework pre-renders HTML on the server, the browser receives static markup (HTML, JS and CSS). React then runs on the client and attaches event listeners and internal state to that markup.
|
||||
Hydration bridges static HTML (build time) and interactive React behavior (run time).
|
||||
|
||||
You only need hydration if you have server-rendered HTML that must become interactive.
|
||||
|
||||
---
|
||||
|
||||
### Next.js: What it adds
|
||||
|
||||
Next.js is a React framework that controls **where** code runs (server vs client), **when** it runs (build vs request time), and how HTML is generated. It adds routing, rendering strategies, data fetching conventions, and server infrastructure.
|
||||
|
||||
Next.js introduces:
|
||||
|
||||
- Server Components vs Client Components
|
||||
- Route-based rendering
|
||||
- Built-in server rendering pipelines
|
||||
- Build-time optimizations
|
||||
|
||||
---
|
||||
|
||||
### Client vs Server in Next.js
|
||||
|
||||
**Server Components:**
|
||||
|
||||
- Render **on the server**, never shipped to the client.
|
||||
- Can safely access databases, filesystem, secrets.
|
||||
- Output is serialized to HTML + a data format React uses to assemble the UI.
|
||||
|
||||
**Client Components (`"use client"`):**
|
||||
|
||||
- Render **in the browser**.
|
||||
- Shipped to the client as JS bundles.
|
||||
- Needed for interactivity (state, events, effects).
|
||||
|
||||
Notes:
|
||||
|
||||
- You can mix Server and Client components; the boundary matters for bundle size and where code executes.
|
||||
- Only Client Components hydrate.
|
||||
|
||||
---
|
||||
|
||||
### Build-Time vs Run-Time
|
||||
|
||||
#### Build-Time (during `next build`)
|
||||
|
||||
- The compiler analyzes the app, identifies server boundaries, optimizes routing.
|
||||
- Static pages (SSG) are rendered to final HTML.
|
||||
- Partial data may be pre-fetched if using static data functions.
|
||||
- Bundles for client components are built.
|
||||
|
||||
#### Run-Time
|
||||
|
||||
- Server Components for SSR are executed on each request.
|
||||
- Serverless or edge functions run as needed.
|
||||
- Client Components hydrate and run effects in the browser.
|
||||
|
||||
---
|
||||
|
||||
### Rendering Strategies
|
||||
|
||||
#### SSR (Server-Side Rendering)
|
||||
|
||||
- Used a webpage or API endpoint (to get server-side data like build ID).
|
||||
- Generated on **every request**.
|
||||
- Good for dynamic data that must be fresh.
|
||||
- Initial load: server renders HTML → client hydrates.
|
||||
- Runs server logic each time a user requests the page.
|
||||
|
||||
Can be dynamic or edge.
|
||||
###### λ (Dynamic)
|
||||
|
||||
- **Server-rendered on demand using Node.js**
|
||||
- Each request hits a Node.js server (or serverless function)
|
||||
- Full access to Node APIs, filesystem, secrets, DB connections
|
||||
- Typical use: **SSR pages with dynamic data** not suitable for edge
|
||||
- Latency depends on server location
|
||||
|
||||
###### ℇ (Edge Runtime)
|
||||
|
||||
- **Server-rendered on demand using Edge Runtime**
|
||||
- Runs on global edge nodes (CDN locations)
|
||||
- Faster response due to geographic proximity
|
||||
- Limited APIs: no filesystem, limited Node.js modules, mostly fetch and standard web APIs
|
||||
- Typical use: **low-latency SSR or ISR at the edge**
|
||||
|
||||
#### SSG (Static Site Generation)
|
||||
|
||||
- HTML is generated **at build time**.
|
||||
- Served as static files.
|
||||
- Zero server cost at request time.
|
||||
- Best for data that changes rarely.
|
||||
|
||||
#### ISR (Incremental Static Regeneration)
|
||||
|
||||
- A hybrid of SSG + scheduled revalidation.
|
||||
- Page is generated at build, then regenerated **in the background** after a specified interval.
|
||||
- Allows static pages with reasonably fresh content without full rebuilds.
|
||||
|
||||
Example behavior:
|
||||
|
||||
- First request after the revalidation window triggers a background regeneration.
|
||||
- Users keep seeing the old page until the new one is ready, then updates swap in.
|
||||
|
||||
There are components that:
|
||||
|
||||
- Run once **on the server** to generate HTML (SSR phase)
|
||||
- Then run again **in the browser** for hydration (client phase)
|
||||
|
||||
---
|
||||
|
||||
### What Runs Where: Quick Table
|
||||
|
||||
| Task / Code | Build Time | Server Run Time | Client Run Time |
|
||||
| -------------------------- | ---------- | ---------------- | --------------- |
|
||||
| Pre-rendering SSG pages | Yes | No | No |
|
||||
| ISR regeneration | No | Yes (background) | No |
|
||||
| SSR rendering | No | Yes | No |
|
||||
| React event handling | No | No | Yes |
|
||||
| `useEffect` | No | No | Yes |
|
||||
| Server Component rendering | No | Yes | No |
|
||||
| Client Component hydration | No | No | Yes |
|
||||
|
||||
---
|
||||
|
||||
# 1. Component Type Detection
|
||||
|
||||
## A. **Client Component (App Router)**
|
||||
|
||||
A component is a **Client Component** if:
|
||||
|
||||
- The file begins with `"use client"`, or
|
||||
- It uses **client-only hooks** (`useState`, `useEffect`, `useRef`, etc.), or
|
||||
- It references **browser APIs** (`window`, `document`, `localStorage`, etc.), or
|
||||
- It uses **client navigation** (`Router.replace`, `useRouter`), or
|
||||
- It uses **interactive JSX handlers**: `onClick`, `onSubmit`, etc.
|
||||
|
||||
**Implications:**
|
||||
|
||||
- Runs **only in browser**
|
||||
- **Hydrates** on the client
|
||||
- **No SSR** of its data
|
||||
- May receive HTML shell from server, but logic/data loads on client
|
||||
|
||||
Client Components = browser-only, hydrated, interactive.
|
||||
|
||||
---
|
||||
|
||||
## B. **Server Component (App Router)**
|
||||
|
||||
A component is a **Server Component** if:
|
||||
|
||||
- No `"use client"`
|
||||
- No client hooks
|
||||
- No browser APIs
|
||||
- No interactive handlers
|
||||
- Uses server-only capabilities (DB queries, file system, server fetch, secrets)
|
||||
|
||||
**Implications:**
|
||||
|
||||
- Runs on **server at build time** (if static) and/or **server at request time**
|
||||
- **No hydration** for the server part
|
||||
- Can output HTML directly
|
||||
- Can trigger SSG / SSR / ISR depending on cache mode or revalidate
|
||||
|
||||
---
|
||||
|
||||
# 3. Rendering Strategy (Pages Router Rules)
|
||||
|
||||
In the **Pages Router**, rendering is dictated entirely by which data-fetching function you export.
|
||||
|
||||
Below are the functions and exactly what they imply.
|
||||
|
||||
---
|
||||
|
||||
# 4. `getServerSideProps` — What It Does and What It Implies
|
||||
|
||||
```js
|
||||
export async function getServerSideProps(context) { ... }
|
||||
```
|
||||
|
||||
### What it does:
|
||||
|
||||
- Runs **on the server for every request**.
|
||||
- Provides props to the page component.
|
||||
- Has access to:
|
||||
- database
|
||||
- filesystem
|
||||
- environment variables
|
||||
- cookies, headers, auth context
|
||||
|
||||
### What it implies:
|
||||
|
||||
- The page is **SSR** (Server-Side Rendered).
|
||||
- HTML is generated **on each request**.
|
||||
- **No SSG** or ISR possible.
|
||||
- The page is never static.
|
||||
|
||||
### Rendering outcome:
|
||||
|
||||
- **SSR HTML** + hydration for any client-side React in the page.
|
||||
|
||||
---
|
||||
|
||||
# 5. `getStaticProps` — What It Does and What It Implies
|
||||
|
||||
```js
|
||||
export async function getStaticProps(context) { ... }
|
||||
```
|
||||
|
||||
### What it does:
|
||||
|
||||
- Runs **once at build time**.
|
||||
- Fetches data needed for static generation.
|
||||
- Provides props to the component.
|
||||
|
||||
### What it implies:
|
||||
|
||||
- The page is **SSG** (Static Site Generated).
|
||||
- The output is static HTML + static JSON.
|
||||
- Zero server rendering at request time.
|
||||
|
||||
### Rendering outcome:
|
||||
|
||||
- **Purely static HTML** served from CDN.
|
||||
- Hydration if component includes client logic (but no server execution).
|
||||
|
||||
### When ISR occurs:
|
||||
|
||||
- If you return `{ revalidate: N }` from `getStaticProps`, the page becomes **ISR**.
|
||||
|
||||
Example ISR config:
|
||||
|
||||
```js
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: { ... },
|
||||
revalidate: 60 // seconds
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. `getStaticPaths` — What It Does and What It Implies
|
||||
|
||||
Used for **dynamic SSG pages** (e.g., `[id].js`).
|
||||
|
||||
```js
|
||||
export async function getStaticPaths() { ... }
|
||||
```
|
||||
|
||||
### What it does:
|
||||
|
||||
- Runs **at build time**.
|
||||
- Tells Next.js which dynamic routes to pre-render.
|
||||
- Works together with `getStaticProps`.
|
||||
|
||||
### What it implies:
|
||||
|
||||
- Page is **SSG** or **ISR** depending on `getStaticProps`.
|
||||
- The routing structure is fixed at build time unless fallback mode is used.
|
||||
|
||||
### Fallback modes define run-time:
|
||||
|
||||
- `fallback: false` → Only pages listed exist; 404 for others
|
||||
- `fallback: true` → Generate pages at runtime, then cache them as static
|
||||
- `fallback: "blocking"` → Block until server generates static page
|
||||
|
||||
Fallback generation effectively behaves like **ISR** for pages not pre-rendered.
|
||||
|
||||
---
|
||||
|
||||
# 7. Summary Table (Pages Router)
|
||||
|
||||
| Export | When It Runs | Rendering Model | Triggered By |
|
||||
| -------------------- | -------------------- | -------------------------------------- | --------------------------- |
|
||||
| `getServerSideProps` | On **every request** | **SSR** | Always dynamic |
|
||||
| `getStaticProps` | **Build time** | **SSG** (or **ISR** with `revalidate`) | No runtime server |
|
||||
| `getStaticPaths` | **Build time** | **SSG** for dynamic routes | Works with `getStaticProps` |
|
||||
|
||||
---
|
||||
|
||||
# 8. Combining Rules: How to Infer Rendering from Code
|
||||
|
||||
### If you see `getServerSideProps`:
|
||||
|
||||
- The page is always **SSR**
|
||||
- Component receives props from server
|
||||
- Component itself is a normal React component rendered server-side then hydrated
|
||||
- No client data loading unless the component explicitly fetches in browser
|
||||
|
||||
### If you see `getStaticProps`:
|
||||
|
||||
- The page is **SSG** or **ISR**
|
||||
- Only runs again during revalidation
|
||||
- Component is static unless you add client-side fetching
|
||||
|
||||
### If you see `getStaticPaths`:
|
||||
|
||||
- The file uses dynamic **SSG** or **ISR**
|
||||
- Builds static versions of dynamic routes
|
||||
|
||||
### If you see `"use client"`:
|
||||
|
||||
- Entire file is **client-rendered**
|
||||
- Data in this component does **not** SSR
|
||||
- Even if the page uses SSG/SSR, this component runs only in browser
|
||||
|
||||
### If you see hooks (`useState`, `useEffect`, etc.):
|
||||
|
||||
- The component must be **client-side**
|
||||
- It must hydrate
|
||||
- It cannot participate in server rendering logic
|
||||
- SSG/SSR/ISR still occurs for the page shell, but the logic inside this component runs only in browser
|
||||
|
||||
### If you see server-side code (DB queries, secrets):
|
||||
|
||||
- Component must be **Server Component** (App Router) or handled inside `getServerSideProps`/`getStaticProps`
|
||||
|
||||
---
|
||||
|
||||
### How to Think About It When Architecting
|
||||
|
||||
1. **Default to Server Components** whenever no browser interactivity is needed.
|
||||
Reduces bundle size and avoids unnecessary hydration.
|
||||
|
||||
2. **Use Client Components** only where interaction happens (buttons, forms, animations, local state).
|
||||
|
||||
3. **Choose a rendering model based on data volatility**:
|
||||
- Rarely changing: SSG
|
||||
- Somewhat changing and OK with slightly stale: ISR
|
||||
- Must always be fresh or personalized: SSR
|
||||
|
||||
4. **Remember:** Hydration cost scales with the amount of Client Components. Keep them narrow.
|
||||
|
||||
5. **Consider caching**:
|
||||
Next.js can automatically cache server component results; knowing what is cached impacts performance heavily.
|
||||
|
||||
|
||||
### Backend vs Frontend on Next.js
|
||||
|
||||
| Term | True Meaning | Might Confuse People Because… |
|
||||
| ------------ | ------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
|
||||
| **Frontend** | Code that executes in the user’s environment (browser, WebView) | SSR code _belongs to frontend logic_ but executes on server |
|
||||
| **Backend** | Code that executes on remote infrastructure (server, VM, cloud function) | Some “backend-like” behavior can occur in browser via caching or local APIs |
|
||||
|
||||
### Downtime
|
||||
|
||||
To simulate downtime **you need the error to happen at runtime, not at build time**. That means the page must be **server-rendered**, not statically generated.
|
||||
Reference in New Issue
Block a user