|
|
@@ -4,8 +4,10 @@
|
|
|
|
|
|
## 环境要求
|
|
|
|
|
|
-- Node.js >= 18.20.7
|
|
|
-- pnpm >= 9
|
|
|
+- Node.js >= 22.12.0(React Router v7 framework 模式 + Vite 7 要求)
|
|
|
+- pnpm >= 10
|
|
|
+
|
|
|
+> 依赖统一用 pnpm 命令管理(`pnpm add` / `pnpm add -D`),勿手改 package.json 版本号,否则会与 lockfile 不一致导致 `frozen-lockfile` 安装失败。
|
|
|
|
|
|
## 快速开始
|
|
|
|
|
|
@@ -16,16 +18,31 @@ pnpm dev
|
|
|
|
|
|
浏览器访问控制台输出的本地地址即可。
|
|
|
|
|
|
+## 渲染模式(CSR / SSG)
|
|
|
+
|
|
|
+项目支持两种渲染模式,**同一份代码、构建时切换**(互斥,一次只出一种产物)。两种模式与 `--mode`(环境:localdev/development/test/production)**正交**,通过不同的 npm script 选择(脚本内部用 `APP_RENDER_MODE` 环境变量传给 `vite.config.ts`)。
|
|
|
+
|
|
|
+| 模式 | 入口 | 路由 | i18n | 产物 | 适用 |
|
|
|
+| --- | --- | --- | --- | --- | --- |
|
|
|
+| **SSG**(默认) | `root.tsx` / `entry.client.tsx` | `/:lang/home`(路径前缀多语言) | `frameworkI18n.ts`(同步 init) | `dist/client/`(预渲染静态 HTML) | 需爬虫/SEO 可见内容,官网/落地页 |
|
|
|
+| **CSR** | `index.html` / `main.tsx` | `/home`(无语言前缀) | `i18n/index.ts`(LanguageDetector 异步) | `dist/`(空壳 SPA) | 纯单页应用,无预渲染需求 |
|
|
|
+
|
|
|
+> 两套入口、路由(`src/routes.ts` vs `src/router/`)、i18n 并存且**完全独立**,由 `APP_RENDER_MODE` 决定实际加载哪套。详见 [SSG 架构文档](./docs/SSG.md)。
|
|
|
+
|
|
|
## 脚本说明
|
|
|
|
|
|
| 命令 | 说明 |
|
|
|
-|------|------|
|
|
|
-| `pnpm dev` | 本地开发(使用 `.env.localdev` + `.env`) |
|
|
|
-| `pnpm build` | 生产构建(等价于 `build:prod`) |
|
|
|
-| `pnpm build:dev` | 开发模式构建(`.env.development`) |
|
|
|
-| `pnpm build:prod` | 生产模式构建(`.env.production`) |
|
|
|
-| `pnpm build:test` | 测试环境构建(`.env.test`) |
|
|
|
-| `pnpm preview` | 预览构建产物(使用 localdev 模式) |
|
|
|
+| --- | --- |
|
|
|
+| `pnpm dev` | 本地开发(默认 = `dev:ssg`) |
|
|
|
+| `pnpm dev:ssg` / `pnpm dev:csr` | 指定模式本地开发(`.env.localdev`) |
|
|
|
+| `pnpm build` | 生产构建(默认 = `build:ssg:prod`) |
|
|
|
+| `pnpm build:ssg:{dev,test,prod}` | SSG 模式各环境构建 → `dist/client/` |
|
|
|
+| `pnpm build:csr:{dev,test,prod}` | CSR 模式各环境构建(先 tsc,再 vite build) → `dist/` |
|
|
|
+| `pnpm build:dev` / `build:test` / `build:prod` | 默认模式(SSG)各环境构建别名 |
|
|
|
+| `pnpm typecheck` | 生成路由类型并做 TS 类型检查(`react-router typegen && tsc`) |
|
|
|
+| `pnpm preview` | 预览 SSG 产物(= `preview:ssg`) |
|
|
|
+| `pnpm preview:ssg` | 用 sirv 静态伺服 `dist/client/`(端口 8848) |
|
|
|
+| `pnpm preview:csr` | 用 sirv 静态伺服 `dist/`(端口 8848) |
|
|
|
| `pnpm lint` / `pnpm lint:fix` | ESLint 检查 / 自动修复 |
|
|
|
| `pnpm stylelint` / `pnpm stylelint:fix` | 样式检查 / 自动修复 |
|
|
|
|
|
|
@@ -34,9 +51,9 @@ pnpm dev
|
|
|
通过不同 `.env` 文件区分环境,Vite 按 **mode** 加载:
|
|
|
|
|
|
| 文件 | 何时加载 |
|
|
|
-|------|----------|
|
|
|
+| --- | --- |
|
|
|
| `.env` | 始终加载(公共默认) |
|
|
|
-| `.env.localdev` | `pnpm dev` / `pnpm preview`(`--mode localdev`) |
|
|
|
+| `.env.localdev` | `pnpm dev`(`--mode localdev`) |
|
|
|
| `.env.development` | `pnpm build:dev` |
|
|
|
| `.env.production` | `pnpm build` / `pnpm build:prod` |
|
|
|
| `.env.test` | `pnpm build:test` |
|
|
|
@@ -47,19 +64,21 @@ pnpm dev
|
|
|
## 技术栈
|
|
|
|
|
|
- **框架**:React 18、TypeScript
|
|
|
-- **构建**:Vite 6、pnpm
|
|
|
+- **构建**:Vite 7、pnpm
|
|
|
+- **渲染**:双模式(构建时切换)——SSG(React Router v7 framework 模式 + 静态预渲染,默认)/ CSR(传统单页应用)。详见 [渲染模式](#渲染模式csr--ssg) 与 [SSG 架构文档](./docs/SSG.md)
|
|
|
- **UI**:Ant Design 5、Tailwind CSS、SCSS/Less
|
|
|
-- **路由**:React Router 7
|
|
|
+- **路由**:React Router 7(SSG 用 `/:lang/...` 路径前缀多语言;CSR 用 `/home` 无前缀)
|
|
|
- **状态**:基于 Context + Hooks 的 Model 方案(类 Umi max)
|
|
|
-- **国际化**:i18next(zh-CN / en-US / fa-IR)
|
|
|
-- **请求**:Axios 封装(`src/utils/request`)
|
|
|
+- **国际化**:i18next(SSG 用 `src/i18n/frameworkI18n.ts` 同步 init;CSR 用 `src/i18n/index.ts` LanguageDetector 异步)
|
|
|
+- **请求**:Axios 封装(`src/utils/request`),请求体 brotli 压缩(brotli-wasm)
|
|
|
- **图标**:@iconify/react + 自定义 SVG 转 Iconify 插件
|
|
|
- **规范**:ESLint、Prettier、Stylelint、Commitlint、Husky、lint-staged
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
```
|
|
|
-├── build/ # Vite 构建相关(插件、工具)
|
|
|
+├── build/ # Vite 构建相关(插件、工具、分包/压缩/服务配置)
|
|
|
+│ └── config/ # 细粒度 Vite 配置模块(chunks、build、plugins、server、optimize)
|
|
|
├── public/ # 静态资源
|
|
|
├── src/
|
|
|
│ ├── assets/ # 资源
|
|
|
@@ -72,15 +91,18 @@ pnpm dev
|
|
|
│ ├── layouts/ # 布局
|
|
|
│ ├── locales/ # 多语言文案(zh-CN、en-US、fa-IR)
|
|
|
│ ├── models/ # 全局状态 Model
|
|
|
-│ ├── pages/ # 页面(按页面分目录)
|
|
|
-│ ├── router/ # 路由配置
|
|
|
+│ ├── pages/ # 页面(按页面分目录,直接作为 route module)
|
|
|
+│ ├── routes/ # framework 路由用的包装组件(langLayout、rootRedirect 等)
|
|
|
│ ├── services/ # API 接口(按模块分目录)
|
|
|
│ ├── styles/ # 全局样式
|
|
|
│ ├── utils/ # 工具与 request 封装
|
|
|
-│ ├── App.tsx
|
|
|
-│ └── main.tsx
|
|
|
+│ ├── root.tsx # HTML 外壳 + Provider 层(取代 index.html/App.tsx)
|
|
|
+│ ├── routes.ts # framework 路由配置(含 /:lang 前缀)
|
|
|
+│ ├── entry.client.tsx # 客户端入口(hydrateRoot,取代 main.tsx)
|
|
|
+│ └── entry.server.tsx # 构建期预渲染入口
|
|
|
├── types/ # 全局类型与 env 类型
|
|
|
-├── index.html
|
|
|
+├── docs/SSG.md # SSG / framework 模式架构文档
|
|
|
+├── react-router.config.ts # framework 模式配置(ssr:false + prerender)
|
|
|
├── vite.config.ts
|
|
|
└── package.json
|
|
|
```
|
|
|
@@ -92,7 +114,7 @@ pnpm dev
|
|
|
- 组件:函数组件 + Hooks;样式优先 Tailwind,必要时 SCSS/Less
|
|
|
- 用户可见文案全部走 `locales`,禁止在代码中硬编码
|
|
|
- 常量与枚举放在 `src/defines/`,请求在 `src/services/` 按模块组织
|
|
|
-- 新页面:在 `src/pages/` 下建目录、在 `routes` 与 `locales` 中注册
|
|
|
+- 新页面:在 `src/pages/` 下建目录、在 `src/routes.ts` 中注册路由、在 `locales` 补文案;若页面需预渲染,在 `react-router.config.ts` 的 `prerender()` 中加路径(详见 [SSG 架构文档](./docs/SSG.md))
|
|
|
|
|
|
## 状态管理(Model)
|
|
|
|
|
|
@@ -127,5 +149,12 @@ pnpm dev
|
|
|
|
|
|
## 部署
|
|
|
|
|
|
-- 构建产物在 `dist/`,将对应环境(如 test/production)的构建结果部署到静态服务器或 CDN 即可。
|
|
|
-- 多环境通过上述 `build:dev` / `build:test` / `build:prod` 与对应 `.env.*` 区分。
|
|
|
+- 构建产物在 **`dist/client/`**(framework 模式产物结构,非旧的 `dist/`),将对应环境的构建结果部署到静态服务器或 CDN 即可。`ssr:false` 为纯静态预渲染,**无需常驻 Node 服务**,对 CDN 加速零影响。
|
|
|
+- 预渲染路径在 `react-router.config.ts` 的 `prerender()` 中配置;未预渲染的路径由 SPA fallback(`dist/client/index.html`)承载。
|
|
|
+- nginx 需配置 SPA fallback 兜底(详见 [SSG 架构文档](./docs/SSG.md)):
|
|
|
+ ```nginx
|
|
|
+ location / {
|
|
|
+ try_files $uri $uri/ $uri.html /index.html;
|
|
|
+ }
|
|
|
+ ```
|
|
|
+- 多环境通过 `build:dev` / `build:test` / `build:prod` 与对应 `.env.*` 区分。
|