---
title: "React + TypeScript + SSR：先手寫一次 raw SSR，再進 Next.js"
description: "想真的搞懂 React SSR，先用 Vite + react-dom/server 手工串一次 SSR，看清 renderToPipeableStream、hydrateRoot 這些 React 原生 API 在幹嘛，再進到 Next.js 看框架幫助我們什麼。"
lang: "zh-Hant-TW"
tags: ["React", "TypeScript", "SSR", "Next.js", "Vite"]
pubDate: 2026-06-05T00:00:00.000Z
updatedDate: 2026-06-09T00:00:00.000Z
---

想**真的搞懂**「React + TypeScript 做 SSR」（而不是照某個框架教學複製貼上），這篇推薦的主線是：**①先用最原生的 Vite + React 親手 wire 一次 SSR**，看清 SSR／SSG 在幹嘛、native 工具就能滿足哪些主流需求；**②再進最主流的 wrapper（Next.js）**，看它為什麼要多包這層、大家用它是換到什麼好處。

其餘的選項（Remix、React Router framework mode、TanStack Start…）等這條主幹走完、建立判斷基準後再橫向比較最划算，所以都放在最後的「接下來學什麼」。

> [!NOTE]
> **為什麼主幹只有「raw SSR」和「Next.js」兩站？** 因為**先理解問題、再理解 wrapper**，才不會把框架的慣例誤當成 SSR 的本質。raw 那一站呈現「不靠任何框架，native 工具到底能做到哪」；Next.js 那一站是目前**壓倒性最主流的 wrapper**（npm 週下載 [~39M](https://npmtrends.com/next)、[State of JS meta-framework 使用第一](https://2024.stateofjs.com/en-US/libraries/meta-frameworks/)），是 CP 值最高的第二步。在第二步，本篇也**刻意只談框架本身（開源、可自架）、略過只能綁在 Vercel 平台上的服務**。其餘框架、以及「Remix 到底去哪了」，放最後延伸。

> [!TIP]
> **先備：JS runtime 這層**。下面會常出現 Node server、Edge runtime、Web Streams、`renderToReadableStream` 這些字。若「JS runtime 到底是什麼、Node 跟 Edge runtime 為何不一樣、為什麼 React SSR 有兩個串流 API」仍然模糊，建議先讀 [JavaScript Runtime](/articles/frontend-to-fullstack/javascript-runtimes)，SSR 整個討論建在那層之上。

## 為什麼值得學

- **SSR 已經是現代 React 的預設值，不是進階選項。** Next.js 的 `create-next-app` [預設就是伺服器渲染的 App Router](https://nextjs.org/blog/next-16)。看懂這層，等於看懂現代 React 應用的骨架。
- **想真懂它，最短路是「先手寫、再看 wrapper」。** [Vite 官方 SSR 指南](https://vite.dev/guide/ssr)自己就說，它的 SSR API「is a low-level API meant for library and framework authors」，做 app 該用更高層的框架，所以**親手 wire 一次是為了「看懂」，Next.js 則是「交付」**，這個分工官方文件自己就講明了。
- **走完這條主幹，就會多一把判斷的尺。** 之後遇到任何框架（Remix、RR7、TanStack…），都可以問「它在 raw 之上多解了哪個問題？專案到底有沒有那個問題？」，而不是被行銷話術或預設值牽著走。

## 定位與脈絡

### 先有問題意識：SSR、SSG、CSR、RSC 各在解什麼問題

下手之前，這邊先簡單介紹**在解什麼問題、又各自帶來什麼新問題**。這段演進史本身，就是評估任何框架時都該保留的問題意識。

最權威的脈絡整理是 web.dev 的 [Rendering on the Web](https://web.dev/articles/rendering-on-the-web)（Addy Osmani & Jason Miller），它把這些做法排成「a spectrum」，用 TTFB、FCP、INP、TBT 幾個指標權衡（定義都在那篇文章裡）。

一句話抓重點：「One of the core decisions web developers must make is **where** to implement logic and rendering」，差別只在「在哪裡 render、何時 render」。

- **[CSR（client-side rendering）](https://developer.mozilla.org/en-US/docs/Glossary/CSR)**：「Rendering an app in a browser, using JavaScript to modify the DOM.」SPA 時代的預設。互動豐富、體驗像 app。**新問題**：首屏是一張空白頁、要等 JS 下載執行才有內容，SEO 與首屏速度都差。
- **[SSR（server-side rendering）](https://developer.mozilla.org/en-US/docs/Glossary/SSR)**：「Rendering an app on the server to send HTML, rather than JavaScript, to the client.」**解決** CSR 的首屏與 SEO。**新問題**：(1) 要養一台會跑 app 的 server（成本與複雜度）；(2) 要處理 **hydration**，也就是 HTML 內已經有了初次 rendering 的結果，載入的 JS app 要怎麼綁上去？(3) 收到 request 時才跑 rendering，產生 HTML 的速度取決於 server 的處理速度
- **[SSG／靜態渲染（static site generator）](https://developer.mozilla.org/en-US/docs/Glossary/SSG)**：build time 時就替每個 URL 建好 HTML。**解決** SSR 要養 server 的問題，成本更低、速度更快。**新問題**：怎麼決定哪些網址要先建好 HTML？頁面哪些部分建進 HTML？request 時才知道的動態資料怎麼辦？

**靜態 ↔ 動態之間的平衡和組合**：早期只能二選一。Next.js 說過：「Prior to PPR, Next.js had to choose whether to render each URL statically or dynamically; **there was no middle ground**.」後來有了 ISR、串流 SSR、以及 [PPR／Cache Components](https://nextjs.org/blog/next-16) 等進階技術：同一頁先送 build time 建好的靜態殼，動態區塊隨後串流補上。

主流的 React SSR wrapper 其實不只一個（Next.js、React Router v7、TanStack Start…），但**它們全都站在同一組 primitive 之上**。要建立判斷力，最短的路是：先用 native 工具看清那組 primitive（第一站），再看最主流的 wrapper 在上面加了什麼（第二站）；等判斷基準建立後，其餘選項回頭花幾分鐘比較就懂（最後一節）。

### 第一站：raw Vite + React SSR，native 工具已經能做到什麼

先把框架全拿掉，用 Vite + `react-dom/server` + 一支小 server 親手接一次。一次 React SSR 的最小流程長這樣，而 meta-framework 包掉的，就是中間那一整段：

```mermaid
flowchart LR
  A[瀏覽器請求 URL] --> B[Node / Edge server]
  B --> C[路由比對 + 先取好資料]
  C --> D["renderToPipeableStream<br/>（Node 串流）或<br/>renderToReadableStream<br/>（Web/Edge 串流）"]
  D --> E[瀏覽器先看到 HTML]
  E --> F[載入 JS bundle]
  F --> G["hydrateRoot：把事件與狀態綁回既有 DOM"]
  G --> H[變成可互動的 app]
  classDef hide fill:#fde,stroke:#c39;
  class B,C,D,F,G hide
```

關鍵 primitive（這幾個 API 就是 SSR 的本體）：

- **[`renderToPipeableStream`](https://react.dev/reference/react-dom/server/renderToPipeableStream)**：Node 環境的串流 SSR 主力（支援 Suspense 串流、`onShellReady`）。
- **[`renderToReadableStream`](https://react.dev/reference/react-dom/server/renderToReadableStream)**：Web Streams／Edge runtime（Deno、Cloudflare Workers）用這個。
- **[`renderToString`](https://react.dev/reference/react-dom/server/renderToString)**：同步、不支援串流、Suspense 支援有限，官方明講「discouraged」，知道它存在即可。
- **[`hydrateRoot`](https://react.dev/reference/react-dom/client/hydrateRoot)**：client 端把伺服器吐出的 HTML「接管」成可互動。官方警告它「expects the rendered content to be identical with the server-rendered content」，所以**hydration mismatch 要當 bug 修**，這也是框架最常協助避開的坑。

**光是這套 native 組合，就能滿足不少主流需求**：伺服器渲染的頁面（SEO、社群分享預覽的 `<meta>`／OG 標籤都成立）、快的首屏、串流 SSR（搭 Suspense 讓慢的區塊不擋住快的）；連 **SSG 都不必額外框架**，[Vite 官方 SSR 指南的 Pre-Rendering / SSG 一節](https://vite.dev/guide/ssr)就說：「If the routes and the data needed for certain routes are known ahead of time, we can pre-render these routes into static HTML using the same logic as production SSR.」換句話說，一個**內容站、行銷頁、文件站，甚至路由不複雜的中小型 app，raw 工具其實就交付得了**。

**而開始麻煩的地方，正好就是 wrapper 的賣點**：巢狀路由 + 每條路由的 data loading 慣例、自動的 per-route code-splitting、巢狀 layout、快取策略、表單／mutation 的一致寫法，以及把上面這些「一致、不出錯地」接好的那一大坨 boilerplate。Vite 自己也把話講白：SSR API「is a low-level API meant for library and framework authors」、做 app 請改用更高層的框架。**這就是進第二站的理由**。

### 第二站：Next.js，為什麼多包這層、換到什麼

目前穩定版是 [Next.js 16（2025/10）](https://nextjs.org/blog/next-16)。把第一站「自己接起來麻煩的地方」對照著看，多包這層 wrapper 換到的是：

- **路由與 layout**：file-system routing + 巢狀 layout，不用自己 wire router。
- **自動 code-splitting**：每條路由自動切包、用到時才載入。
- **資料與 mutation**：[RSC](https://react.dev/reference/rsc/server-components)（server component 在伺服器抓資料、那段程式碼不進 client bundle）+ Server Actions（`"use server"`，不必自己手刻 API route 做 mutation）。
- **靜態 ↔ 動態一條龍**：把第一站「要嘛全靜態、要嘛全動態」的二選一補成光譜，像是 SSG、ISR、以及 v16 的 [PPR／Cache Components](https://nextjs.org/blog/next-16)（官方：PPR 之前「there was no middle ground」；v16 起快取「entirely opt-in」）。
- **內建優化與 DX**：`next/image`、`next/font`、[v16 預設且穩定的 Turbopack](https://nextjs.org/blog/next-16)（dev／build 都更快）、TypeScript-first、跑在 [React 19.2 + 穩定的 React Compiler](https://nextjs.org/blog/next-16) 上。
- **最大的生態與慣例**：常見的坑幾乎都有人踩過、有現成答案，這本身就是「最主流 wrapper」最實際的價值。

**誠實的成本**（想避開黑盒的人尤其該知道）：RSC 的 server／client 邊界是一套要重學的心智模型；快取曾經複雜到 [Vercel 自己在 v15 重評預設、v16 改成 opt-in](https://nextjs.org/blog/next-16)；自架雖可行但有摩擦（v16 才推出 [Build Adapters API（alpha）](https://nextjs.org/blog/next-16) 來改善非 Vercel 部署）。

> [!NOTE]
> **關於 Vercel**：上面講的全是**框架本身**（開源、可自架）。本篇刻意略過只能綁在 Vercel 平台上的服務（平台級 analytics、特定 ISR／CDN infra 等）：那些是部署便利，不是「學會一個 SSR 框架」的必要部分。學會框架本身，這套能力就能帶到任何 host。

## 怎麼入手

「定位與脈絡」鋪好兩站的問題意識後，這節照同一條主幹各動手一次：**第一站親手接過 raw SSR、第二站用 Next.js 把同樣的東西重做**。順序有意義，倒過來會把框架慣例誤當 SSR 本質。

兩站的 session 切法不同，因為要消化的東西不同：**第一站要讀的東西少、又跟動手分不開**（每接一個 API 就順手讀那支官方 reference），併成一個「邊動手邊學」的 session 最順；**第二站要先消化的概念較重**（RSC 的 server／client 邊界、快取模型），值得先用一個 session 純讀懂、對齊，再開一個 session 動手。下面幾段 prompt 各自開新對話、依序貼給 agent。

### 第一站：raw Vite + React SSR

把任何 meta-framework 拿掉，用 Vite + React + 一支小 server 親手 wire 一次：HTTP → `renderToPipeableStream` → `hydrateRoot`。目的不是讓未來的 app 都照這種方式寫，而是**看清楚 native primitive 在幹嘛、native 工具到底能做到哪、哪裡開始麻煩**（後者就是第二站要被 wrap 的東西）。

👉 複製這段 prompt 開一個 session：

```
我想真正搞懂「React + TypeScript 做 SSR」的最底層——不照框架教學複製貼上，而是把任何 meta-framework 拿掉、親手把最原生的 raw SSR 接出來，邊做邊看清 native primitive 在幹嘛、native 工具到底能做到哪、哪裡開始痛。請帶我邊動手邊學：每一步都說明在做什麼、對到哪個 API、附上引用的官方文件來源，並講清楚現在落在整個 POC 流程的哪一段；每完成一步先確認我懂了、再問我要不要進下一步。不確定我的程度或環境就先問我。
1. 先給全貌：用一段話描述我們接下來要做出來的 POC 長什麼樣——一支小 Node server 收 URL → renderToPipeableStream 把 HTML 串給瀏覽器 → client 端 hydrateRoot 接管成可互動，之後再加一頁 build time 預渲染的 SSG。我這時不一定全懂，先有張地圖就好，後面逐步補上。
2. 動手做最小可跑的 raw SSR：Vite + React + TS + 一支 Node server，收一個 URL、跑 renderToPipeableStream 把 HTML 串給瀏覽器、client 端 hydrateRoot 接管成可互動。
3. 親手感受 hydration mismatch：故意製造一次（譬如 SSR 渲染了當下時間、client 第一次 render 算出來不一樣），讓我看 React 怎麼警告、再把它修掉，並依 React 官方文件（不要憑記憶）說明為什麼 hydrateRoot 要求 server 與 client 初次 render 一致——讓我內化「hydration mismatch 是 bug、不是警告」。
4. 試 SSG：依 Vite 官方 Pre-Rendering / SSG 那一節（https://vite.dev/guide/ssr），把其中一頁改成 build time 預渲染的靜態 HTML。
5. 檢查：我對上面已有基本理解後，出幾題重點問題問我，讓我用自己的話講一遍；我答完後依 Vite、React 官方文件（不要憑你的記憶）幫我檢查，有需要的話訂正。
6. 痛在哪（下一站的引子）：這支最小 SSR 之上若繼續長成一個 app，哪些事「明顯不該每個 app 自己接」——譬如巢狀路由、每路由的 data loading 慣例、自動 per-route code-splitting、巢狀 layout、表單／mutation 模式——條列出來，當作進第二站時對照「Next.js 多包了什麼」的清單。最後請根據這個 session 的對話歷史，幫我寫一份交接文件 `raw-ssr-handoff.md`，讓我帶著它開第二站的 session。

進行2,3,4時，一邊接一邊帶我讀對應的官方文件、不要憑記憶複述。例如可引用：
   - Vite SSR guide: https://vite.dev/guide/ssr
   - React.dev — renderToPipeableStream: https://react.dev/reference/react-dom/server/renderToPipeableStream
   - React.dev — hydrateRoot: https://react.dev/reference/react-dom/client/hydrateRoot
並且記得提醒一些初學者容易誤解或不懂的地方。

若這個 session 過長、方向變過幾次，或你判斷 context 壓縮可能影響你的理解，提醒我：換新 session 通常會更穩、更準。提醒時一併把目前狀態、決策、待辦、關鍵檔案路徑整理成一份專案內的交接 Markdown 給下一輪 agent 用；沒有合適專案資料夾或任務很輕，就直接把摘要貼進新對話。不要頻繁提醒，只在真的會影響品質時提。
```

### 第二站：Next.js

把第一站做出來的東西用 Next.js（App Router）重做一次，每接一段都明確對到「raw 那邊我自己接的哪一格，現在 Next.js 用什麼 API 幫我做了」。目的是**親眼看到第一站列出來的痛點清單怎麼被 wrapper 一一吸收，並順便碰上 Next.js 多帶進來的兩道概念門檻，也就是 RSC 的 server／client 邊界與快取模型**。

#### 2a. 讀懂 Next.js 在 raw 之上多包了什麼（一個 session）

這站只讀、不動手，目的是動手前先建立**唯一非懂不可的心智模型：RSC 的 server／client 邊界**。**先讀下面這幾頁、形成初步理解**，再把 prompt 貼給 agent 對齊觀念、出題訂正：

- **核心（先讀這兩頁）**：[Next.js — Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components)、[React — `"use client"`](https://react.dev/reference/rsc/use-client)，重點是什麼跑在 server、什麼進 client bundle、邊界為什麼要明示。
- **快取只要掌握一個框架級概念**：v16 起快取 entirely opt-in（預設不快取、要快取要明示），掃一眼 [Next.js 16 blog](https://nextjs.org/blog/next-16) 的快取段即可、不必深讀。
- **想再深一層**（可選）：[React — Server Components](https://react.dev/reference/rsc/server-components)，但不用硬要全部讀完。
- routing、巢狀 layout、Server Actions、PPR 這些細節**這輪先別讀**，下一站動手時自然會碰到。

讀完後，👉 複製這段 prompt 開一個 session：

```
我已經做過第一站、知道 raw SSR 的 primitive 跟自己接的痛點，手上有第一站產出的交接文件 `raw-ssr-handoff.md`，我會貼給你。這個 session 是動手前的概念對齊，下一個 session 才用 Next.js（App Router）動手重做。我已自己讀過下面這幾頁、想先建立 RSC 的 server／client 邊界心智模型，請在對齊與訂正時以它們為準：
- Next.js — Server and Client Components: https://nextjs.org/docs/app/getting-started/server-and-client-components
- React.dev — "use client": https://react.dev/reference/rsc/use-client
- 快取我只先抓一個框架級概念：Next.js 16 起 entirely opt-in（預設不快取、要快取要明示），來源 https://nextjs.org/blog/next-16
請帶我做，不確定就先問我：
1. 別先幫我總結、也別憑記憶重述文件——直接用一段話跟我對齊心智模型就好：RSC 的 server／client 邊界（什麼跑在 server、什麼進 client bundle、`"use client"` 把邊界畫在哪一層），以及「v16 快取預設 opt-in」這一個框架級概念。routing / Server Actions / PPR 的細節先不要展開，留到動手那輪；如果你判斷少了哪一塊會讓我下一輪看不懂，再提出來。
2. 檢查：出兩三題問我（為什麼 RSC 的 server／client 邊界要明示、`"use client"` 該標在哪一層、為什麼說 v16 快取是 opt-in），我答完後依 Next.js、React 官方文件（不要憑你的記憶）幫我訂正。

若這個 session 過長、方向變過幾次，或你判斷 context 壓縮可能影響你的理解，提醒我：換新 session 通常會更穩、更準。提醒時一併把目前狀態、決策、待辦、關鍵檔案路徑整理成一份專案內的交接 Markdown 給下一輪 agent 用；沒有合適專案資料夾或任務很輕，就直接把摘要貼進新對話。不要頻繁提醒，只在真的會影響品質時提。
```

#### 2b. 用 Next.js 重做 + 碰上概念門檻（一個 session）

這站動手重做，親手碰一次 RSC 邊界與快取這兩道門檻。開始前應已做完第一站、也跑過 2a 的概念對齊（手上有 `raw-ssr-handoff.md`）。這站邊做邊學，要讀的官方文件由 agent 在動手時帶著讀，所以下面整段都是給 agent 的，照著貼、跟著做即可。

👉 複製這段 prompt 開一個 session：

```
我做過第一站、手上有第一站產出的交接文件 `raw-ssr-handoff.md`，也跟另一個 session 對齊過 Next.js（App Router）的核心心智模型（RSC 的 server／client 邊界、v16 快取 opt-in）。這個 session 我想用 Next.js 把第一站做過的東西重做一次，並親手碰一次 RSC 邊界與快取這兩道門檻。請帶我邊做邊學：每接一段先說它對到「raw 我自己接的哪一格、現在用 Next.js 哪個 API」、附上對應官方文件（不要憑記憶複述），每完成一步先確認我懂了、再問我要不要進下一步。不確定就先問我（如果發現我其實還沒對齊好概念，請先提醒我回去做完概念那一輪）：
1. 先給全貌：用一段話描述我們接下來會做什麼——用 Next.js App Router 重建第一站那個 app，沿路逐項對到痛點清單，並刻意去碰 RSC 邊界與 v16 快取這兩道門檻。我先有張地圖就好，細節後面逐步補上。
2. 動手：用 Next.js App Router 重做第一站做過的東西——同樣的頁面、同樣的資料、同樣能 hydrate 起來互動。每接一段都明確對到「raw 那邊我自己接的哪一格（路由、data loading、code-splitting、靜態／動態邊界），現在 Next.js 用什麼 API 幫我做了」；file-system routing、巢狀 layout、Server Actions 這些我在概念 session 刻意沒先讀的細節，就在這裡邊做邊帶我讀對應官方文件。我會帶著痛點清單進來，請逐項對到 Next.js 的對應做法。
3. 踩 RSC 邊界：刻意違規一次——譬如在 server component 裡用 useState、或在 client component 裡 import 只能跑在 server 的東西——讓我看清楚錯誤訊息、用「哪個 module 跑在哪邊」的角度修掉它，內化 "use client" 邊界的意義。
4. 看快取：試一個簡單例子體會 Next.js 16 的 cache opt-in 模型——v16 起快取 entirely opt-in，看哪些 fetch / route 預設不快取、要快取要怎麼明示。
5. 對照：用一頁說明同樣的需求，何時 raw 就夠、何時值得多吃 Next.js 這層 wrapper 的複雜度，以及 Next.js 為了換到生態與 DX，誠實的成本（RSC 心智模型、非 Vercel 部署的摩擦）落在哪。

若這個 session 過長、方向變過幾次，或你判斷 context 壓縮可能影響你的理解，提醒我：換新 session 通常會更穩、更準。提醒時一併把目前狀態、決策、待辦、關鍵檔案路徑整理成一份專案內的交接 Markdown 給下一輪 agent 用；沒有合適專案資料夾或任務很輕，就直接把摘要貼進新對話。不要頻繁提醒，只在真的會影響品質時提。
```

## 延伸主題

### 延伸一：raw + Next.js 之外的框架地圖

走完主幹、手上有了尺，再來看橫向選擇。主流的 React SSR wrapper 不只 Next.js；走完主幹後，其餘三條值得認識的路是：

- **React Router v7（framework mode）— 最貼近 web 標準、黑盒最少。** 它有[三種 additive 的 mode](https://reactrouter.com/start/modes)：Declarative → Data（`loader`/`action`/`useFetcher`）→ Framework（Vite plugin + SSR + type-safe `href`／Route Module + code-splitting）。官方原話：「pick your mode based on **how much control or how much help** you want」。由 [Shopify 團隊維護](https://remix.run/blog/merging-remix-and-react-router)，[RSC 仍 experimental](https://reactrouter.com/how-to/react-server-components)。（它就是 Remix 的當代延續；若曾聽過 Remix、好奇那個名字後來去哪了，可以看文末附註。）
- **TanStack Start — 主打型別安全，但整體仍很早期。** [2025/09 v1.0 RC](https://tanstack.com/blog/announcing-tanstack-start-v1)、2026 年中框架本體已到 1.x；賣點是[端對端型別安全、isomorphic server functions、串流 SSR](https://tanstack.com/blog/announcing-tanstack-start-v1)，自我定位「no opaque magic」。代價：相對 Next.js 非常年輕，生態、第三方整合與職缺都還小。
- **走在更前面的 RSC-first：[Waku](https://www.infoq.com/news/2026/02/waku-react-framework/)**（Zustand/Jotai 作者 Daishi Kato、建在 Vite + Hono），代表「RSC 不等於只能用 Next.js」。

實際的採用情況（[npm 官方 API 單週下載](https://npmtrends.com/@remix-run/react-vs-@tanstack/react-start-vs-next-vs-react-router)，2026/06 初；`react-router` 同一個套件也被當作 SPA library 用，所以數字失真）：

| 套件                    | npm 單週下載 | 語意                          |
| ----------------------- | ------------ | ----------------------------- |
| `next`                  | ~39.2M       | 最乾淨的 meta-framework 訊號  |
| `react-router`          | ~47.5M       | 含大量 SPA library 用法，失真 |
| `@tanstack/react-start` | ~14.3M       | 框架新，數字含 CI/transitive  |
| `@remix-run/react`      | ~1.0M        | Remix v2 遺產，退場中         |

一句話該怎麼選：**最大生態／最多職缺／想跟上 RSC 最新進展 → Next.js（主幹已涵蓋）；最透明、黑盒最少 → React Router v7；型別控、願承擔較新框架風險 → TanStack Start。**

<details>
<summary>附註：聽過「Remix」的話，它去哪了？</summary>

Remix 這個名字，這兩年已經分裂成兩個東西：

| 時間    | 事件                                                                                                                                                                                                                          | 實務上的意義                                  |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| 2024/05 | [宣布 Remix 併入 React Router](https://remix.run/blog/merging-remix-and-react-router)：「原訂的 Remix v3 改以 React Router v7 發布」                                                                                          | 「學 Remix」開始等於「學 React Router v7」    |
| 2024/11 | [React Router v7 發布](https://remix.run/blog/react-router-v7)，內含 **framework mode**（= 原本的 Remix）                                                                                                                     | 新專案官方建議直接用 RR v7，不要再起 Remix v2 |
| 2025/05 | [宣布全新「Remix 3」](https://remix.run/blog/wake-up-remix)：不依賴 React、[model-first（為 LLM 最佳化）](https://remix.run/blog/wake-up-remix)、建在 Web API 上、從 [Preact fork](https://remix.run/blog/wake-up-remix) 起家 | 這是**另一個東西**，跟「React + SSR」無關     |
| 2026/04 | [Remix 3 Beta Preview](https://remix.run/blog/remix-3-beta-preview)：仍「not production ready yet」                                                                                                                           | 想嚐鮮可以，別拿來開新產品                    |

所以對「React + SSR」，Remix 的當代延續就是上面的 **React Router v7（framework mode）**；2025 年宣布的「Remix 3」則是另一條與 React 無關的路線。

</details>

### 延伸二：更深的概念

- **React Server Components 深入**：主幹第二站最大的概念門檻，也就是什麼在 server 跑、什麼進 client bundle、`"use client"` 邊界怎麼畫。也值得把 2024–2025 期間「直接接 DB / 像 PHP / 隱形 RPC」這些 bad smell 批評找來讀。「概念該懂」跟「該不該用」是兩回事。
- **Svelte 5 / SvelteKit**：SvelteKit 之於 Svelte，就是這篇的 Next.js 之於 React，把另一個生態的 SSR wrapper 對照著看，更懂「wrapper 到底在解什麼」。
