> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 迁移：从 SSG（旧方案）升级到请求期 SSR（新方案）

> 把已做过 vite-react-ssg SSG 改造的项目，迁移到标准 React Router 7 data-mode 请求期 SSR。SSG=旧方案（构建期预渲染、内容静态）；SSR=新方案（请求期渲染、可带动态实时数据）。复用 SSG 已做的 SSR 安全工作，拆掉 SSG 机制、路由升 RR7 data-mode，目标模板见 seo/ssr。

# 迁移：从 SSG（旧方案）升级到请求期 SSR（新方案）

你是代码迁移 Agent。本指南把**已经做过 SSG 改造**（`vite-react-ssg`）的项目，**迁移**到**标准 React Router 7 data-mode 请求期 SSR**。

> **定位：SSG 是旧方案，SSR 是新方案。** 这是一次**升级迁移**，不是平级切换。
>
> * **SSG（旧）**：构建期把页面预渲染成静态 `.html`。只能渲染**构建期就确定**的内容；数据一变就得重新构建，做不到"请求期带实时数据"。
> * **SSR（新）**：请求期在服务端渲染，能带**动态/实时数据**（DB 驱动、每次请求都新）。是 SSG 的**超集 + 升级**。
>   **何时迁**：**所有 `vite-react-ssg` SSG 项目都要迁到 SSR**——它已是退役旧栈（钉死 react-router v6、不再投入），不论页面内容是动态还是纯静态都升级。**不要**再以"内容是静态的 / SSG 够用"为由保留 SSG。SSR 是 SSG 的超集：静态页迁过去就是**没有 loader 的 SSR**，首屏照样在服务端预渲染出完整内容、SEO/抓取一点不受影响。

**好消息（省一大半）**：SSG 改造时已做的 **SSR 安全工作**——顶层 `window`/`document` 守卫、`Sonner`/主题的 `mounted` 守卫、`framer-motion` `initial=false` 首屏可见、非确定性值稳定化——SSR **完全复用、原样保留**（SSR 与 SSG 是同一批 import 期 + hydration 坑）。所以本迁移**主要是换渲染机制 + 升路由，护栏不用重做**，比从纯 CSR 起步更省。

**目标产物**：标准 RR7 data-mode SSR 工程，与 [CSR→SSR](/superun/skills/seo/ssr) **完全一致**——`entry-server`/`entry-client`、`vite.config.ssr.ts`、单一 `routes.tsx`、route `loader`。这些**模板逐字见 [CSR→SSR 指南 §C](/superun/skills/seo/ssr)**；本指南只讲 SSG 特有的 **delta**。

## A. 必须遵守（MUST）

1. 必须**完全拆掉 SSG 机制**：移除 `vite-react-ssg`（依赖 + `dev`/`build` 脚本 + 相关 vite 插件）、`main.tsx` 里的 `ViteReactSSG` 入口、所有 `getStaticPaths`。
2. 必须把路由从 RR6 的 `RouteRecord[]` / `createRoutesFromElements` 迁到 **RR7 data-mode 的 `RouteObject[]`**（单一 `src/routes.tsx`）。
3. 必须把 `react-router-dom@6` 升到 **`react-router@7`**：v6 被钉死是因为 `vite-react-ssg` 要求；既然本次离开 SSG，这个钉死理由消失——升 v7 让**全平台 SSR 项目统一一个目标**（否则分裂出 v6-SSR / v7-SSR 两套）。
4. 必须**保留** SSG 已做的全部 SSR 安全守卫（见 SSG 指南 D/E/F 的 `mounted`/guard/`initial=false`）——它们对 SSR 同样必需，**原样留、别删了重写**。
5. 必须按 [CSR→SSR 指南 §C](/superun/skills/seo/ssr) 加 `entry-server`/`entry-client`、`vite.config.ssr.ts`、改 `index.html` 入口。

## B. 明确禁止（DO NOT）

1. 不要残留任何 `vite-react-ssg` 痕迹（残留的 `ViteReactSSG`/`getStaticPaths` 会和 RR7 data router 冲突）。
2. 不要把已做好的浏览器守卫 / `mounted` 保护删掉重写——**复用**。
3. 不要手写平台职责的东西（`x-ssr` marker、`render-manifest`、CDN 上传）——平台自动处理，见 [CSR→SSR 指南 §F](/superun/skills/seo/ssr)。

## C. 执行步骤（按顺序）

### 1) 拆 SSG 机制

* `package.json`：移除 `vite-react-ssg` 依赖；`dev`/`build`/`preview` 脚本从 `vite-react-ssg dev|build` 改回标准 `vite` / `vite build`（SSR 的双构建由平台 `release.sh` 见到 `vite.config.ssr.ts` 自动接管）。
* `main.tsx`：移除 `ViteReactSSG(routes, ...)` 入口（将被 `entry-client.tsx` 取代）。
* `vite.config.ts`：清掉 SSG 专属配置（如 `isSsrBuild` 分支里为 SSG 禁用的 `manualChunks` 逻辑）；CDN/资源/alias 等通用配置保留。
* 路由文件：**移除所有 `getStaticPaths`**（请求期 SSR 不需要构建期枚举路径，路径在请求时由 router 匹配）。

### 2) 路由升级：RR6 `RouteRecord[]` → RR7 `RouteObject[]`

* 依赖：`react-router-dom@^6.30.3` → `react-router@^7`（v7 起合并成 `react-router` 单包）。
* 把 `createRoutesFromElements(<Route/>)` 产出的 `RouteRecord[]`（本就是 `RouteObject` 的超集）整理成**显式 `src/routes.tsx` 的 `RouteObject[]`**：`element`/`children`/`path` 大多照搬，**去掉 `getStaticPaths` 等 SSG 专属字段**。
* 导入路径：v6 的 `react-router-dom` → v7 `react-router`（`StaticRouter`/data API 在 v7 都在 `react-router`）。

### 3) 应用 SSR 模板（同 CSR→SSR）

* 照 [CSR→SSR 指南 §C](/superun/skills/seo/ssr)：加 `entry-server.tsx`、`entry-client.tsx`、`vite.config.ssr.ts`，`index.html` 入口改指 `entry-client.tsx`，App 的 providers 收进 `routes.tsx` 根布局。
* 局部深化：原来靠 `getStaticPaths` 预取 / 客户端 `fetch` 的数据，**改成 route `loader`**（服务端取数，见 [CSR→SSR §D](/superun/skills/seo/ssr)），组件 `useLoaderData()` 读。

## D. 复用清单（SSG 已做、SSR 留着别动）

下面这些 SSG 改造时就收敛过的，SSR 同样需要，**原样保留**：

* 顶层 / Hook 初始值里的 `window`/`document`/`localStorage` 守卫。
* `Sonner`/toast 的 `mounted` 守卫、主题（`useTheme`）的挂载一致性。
* `framer-motion` `initial=false` 首屏可见、`useInView` 默认可见。
* 非确定性值（时间戳/随机）的稳定化。

→ 这些是 SSR 同样要过的护栏；SSG 那次已做，本次**直接受益**。

## E. 交付验收（必须全部通过）

1. 项目里**无 `vite-react-ssg` 残留**（依赖/脚本/`getStaticPaths`/`ViteReactSSG` 全清）。
2. `pnpm build` 成功 + 产出 `dist/server/entry-server.js`（同 CSR→SSR 验收）。
3. 路由是单一 `src/routes.tsx` 的 `RouteObject[]`（RR7）。
4. 原 SSG 的 SSR 安全守卫仍在；首屏 hydration 无显著 mismatch。
5. 动态页通过 `loader` 在 SSR 首屏带真实数据；纯静态页正常出壳 + 客户端接管。

## F. 失败处理优先级（按顺序排查）

1. 先查 `vite-react-ssg` 是否拆干净（残留的 `ViteReactSSG`/`getStaticPaths` 会和 RR7 data router 冲突）。
2. 再查 RR6→7 导入路径（`react-router-dom` → `react-router`）与 `react-router` 单份 alias。
3. 其余同 [CSR→SSR 指南 §I 失败处理](/superun/skills/seo/ssr)。
