# react-template
**Repository Path**: overflow_z/react-template
## Basic Information
- **Project Name**: react-template
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-08-06
- **Last Updated**: 2026-08-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# React Template
基于 Vite 8 + React 19 + TypeScript 6 构建的企业级前端开发模板,开箱即用。
## 技术栈
| 类别 | 技术 | 版本 |
|------|------|------|
| 构建工具 | Vite (Rolldown) | 8.2 |
| 框架 | React | 19.2 |
| 类型系统 | TypeScript | 6.0 |
| 样式方案 | Tailwind CSS | 4.3 |
| UI 组件库 | shadcn/ui (base-ui + CVA) | 4.16 |
| 图标库 | Lucide React | 1.28 |
| 动画 | Framer Motion | 13.0 |
| 路由 | TanStack Router | 1.170 |
| 状态管理 | Zustand | 5.0 |
| 数据请求 | TanStack Query | 5.101 |
| 表单 | TanStack Form | 1.33 |
| 代码检查 | Oxlint | 1.75 |
| 测试框架 | Vitest + Testing Library | 4.1 / 16.3 |
| Git Hooks | Lefthook | 2.1 |
| 提交规范 | Commitlint + cz-git | 21.2 / 1.13 |
| Toast 通知 | Sonner | 2.0 |
| 错误边界 | react-error-boundary | 6.1 |
| 缓存 | Web Crypto API + IndexedDB | built-in |
## 目录结构
```
src/
├── components/
│ ├── custom/ # 自定义业务组件
│ │ ├── async-state.tsx # 统一 Loading/Empty/Error 状态组件
│ │ ├── error-boundary.tsx # 错误边界
│ │ ├── error-page.tsx # 通用错误页面(404/403/500)
│ │ ├── route-loading.tsx # 路由加载指示器
│ │ └── theme-toggle.tsx # 主题切换按钮
│ ├── layout/
│ │ └── root-layout.tsx # 根布局(导航栏 + 主题切换)
│ ├── ui/ # shadcn/ui 原生组件(60+)
│ └── theme-provider.tsx # 主题 Provider(dark/light/system)
├── hooks/ # 自定义 Hooks
│ ├── use-mobile.ts # 移动端检测
│ ├── use-nprogress.ts # 路由进度条
│ └── use-query.ts # React Query 封装 hooks
├── lib/
│ ├── cache/ # 缓存模块
│ │ ├── types.ts # 类型定义
│ │ ├── crypto.ts # AES-GCM 加密/解密
│ │ ├── storage.ts # 抽象基类(TTL 过期 + 加密)
│ │ ├── local.ts # localStorage 适配器
│ │ ├── session.ts # sessionStorage 适配器
│ │ ├── indexed-db.ts # IndexedDB 适配器
│ │ └── index.ts # 统一导出 + 全局实例
│ ├── query-client.ts # React Query 全局配置
│ ├── request.ts # HTTP 客户端(qs 序列化 + 多 base URL)
│ └── utils.ts # 工具函数(cn 类名合并)
├── stores/ # Zustand 状态管理
│ ├── __tests__/ # Store 测试
│ └── counter.ts # 计数器示例
├── styles/ # 全局样式
│ ├── globals.css # Tailwind 主题 + 暗色模式
│ └── nprogress.css # 进度条样式
├── types/
│ └── env.d.ts # 环境变量类型声明
├── views/ # TanStack Router 文件路由(自动生成)
│ ├── __root.tsx # 根路由(布局 + 过渡动画)
│ ├── index.tsx # 首页
│ ├── about.tsx # 关于页
│ ├── dashboard.tsx # 仪表盘
│ ├── settings.tsx # 设置页
│ ├── -not-found.tsx # 404 页面
│ ├── -forbidden.tsx # 403 页面
│ └── -server-error.tsx # 500 页面
├── main.tsx # 应用入口
├── routeTree.gen.ts # 自动生成的路由树
├── test-setup.ts # 测试环境配置
└── vite-env.d.ts # Vite 类型声明
```
## 快速开始
```bash
# 安装依赖(推荐使用 pnpm)
pnpm install
# 启动开发服务器
pnpm dev
# 构建生产版本
pnpm build
# 预览生产构建
pnpm preview
```
## 可用脚本
| 命令 | 说明 |
|------|------|
| `pnpm dev` | 启动开发服务器(HMR) |
| `pnpm build` | 生产环境构建 |
| `pnpm preview` | 预览生产构建产物 |
| `pnpm typecheck` | TypeScript 类型检查 |
| `pnpm lint` | 代码规范检查(Oxlint) |
| `pnpm test` | 运行单元测试 |
| `pnpm test:coverage` | 测试覆盖率报告 |
| `pnpm commit` | 使用 cz-git 交互式提交 |
## 开发规范
### 组件规范
- 页面中所有 UI 元素必须使用 shadcn/ui 组件,禁止手动编写原生 HTML 元素
- 自定义业务组件放在 `src/components/custom/`,shadcn 原生组件放在 `src/components/ui/`
- 仅使用函数组件,禁止使用 Class 组件
- 组件文件使用 PascalCase 命名(如 `UserProfile.tsx`)
- 导航跳转必须使用 `useNavigate` hook,禁止使用 `` 标签
### 命名约定
| 类型 | 风格 | 示例 |
|------|------|------|
| 组件/类 | PascalCase | `UserProfile` |
| 函数/变量 | camelCase | `getUserInfo` |
| 常量 | UPPER_SNAKE_CASE | `API_BASE_URL` |
| 文件名 | PascalCase / kebab-case | `UserProfile.tsx` |
### Git 提交规范
使用 Angular 提交规范,通过 `pnpm commit` 交互式提交:
```
():
feat: 新功能
fix: 修复 Bug
docs: 文档更新
style: 代码格式(不影响功能)
refactor: 重构
perf: 性能优化
test: 测试相关
chore: 构建/工具链变更
```
### Git Hooks
| Hook | 行为 |
|------|------|
| pre-commit | Oxlint 检查 + TypeScript 类型检查 |
| commit-msg | 校验提交信息是否符合 Angular 规范 |
| pre-push | 运行测试 + 构建验证 |
## 主题
支持浅色/深色/跟随系统三种模式,通过导航栏右侧的太阳/月亮图标切换。主题偏好保存在 localStorage 中。
```tsx
import { useTheme } from "@/components/theme-provider";
const { theme, setTheme } = useTheme();
setTheme("dark"); // "light" | "dark" | "system"
```
主题色在 `src/styles/globals.css` 中通过 CSS 变量控制,修改 `--primary` 即可全局切换:
```css
:root {
--primary: #3b82f6; /* 主色 */
--primary-foreground: #ffffff; /* 主色上的文字颜色 */
}
```
## HTTP 请求
模板内置了基于 Fetch API 的 HTTP 客户端,支持:
- 请求/响应拦截
- 自动 Toast 错误提示(sonner)
- 静默模式(不弹错误提示)
- HTTP 状态码 + 业务错误码双重处理
- qs 参数序列化(支持嵌套对象和数组)
- 多 base URL 客户端
```ts
import { http, httpClients } from "@/lib/request";
// GET 请求(参数自动 qs 序列化)
const users = await http.get("/users", { params: { page: 1 } });
// POST 请求(静默错误)
await http.post("/api/data", payload, { silent: true });
// 使用命名客户端
const userData = await httpClients.user.get("/profile");
```
### React Query 封装
```tsx
import { useGet, usePost, useUsers } from "@/hooks/use-query";
// 通用 hooks
const { data, isLoading } = useGet(["users"], "/users", { page: 1 });
const { mutate } = usePost("/users");
// 业务 hooks
const { data: users } = useUsers();
```
## 缓存
内置统一缓存模块,支持 localStorage / sessionStorage / IndexedDB 三种后端,统一 API:
```ts
import { storage, session, indexedDB } from "@/lib/cache";
// 同步读写(localStorage / sessionStorage,开发环境明文)
storage.set("user", { name: "Tom" }, 5 * 60 * 1000); // 5 分钟过期
const user = storage.get("user");
// 异步读写(支持加密,IndexedDB 必须异步)
await storage.setAsync("token", "abc123"); // 生产环境自动 AES-GCM 加密
const token = await storage.getAsync("token");
await indexedDB.setAsync("bigData", largeObject);
// 自定义实例
import { createLocalCache, createIndexedDBCache } from "@/lib/cache";
const userCache = createLocalCache({ ttl: 60_000, encrypt: false });
const dbCache = createIndexedDBCache({ dbName: "myApp", ttl: 24 * 60 * 60 * 1000 });
```
- **TTL 过期**:设置 `ttl` 参数,数据过期后自动清除
- **加密**:生产环境自动启用 AES-GCM 加密,开发环境明文存储
- **IndexedDB**:异步操作,使用 `getAsync` / `setAsync` / `keysAsync` / `hasAsync`
## 异步状态组件
使用 `AsyncState` 统一处理 loading / empty / error 三种状态:
```tsx
import { AsyncState } from "@/components/custom/async-state";
```
## 错误页面
模板内置了 404、403、500 错误页面,通过 TanStack Router 的 `notFoundComponent` 和 `errorComponent` 自动触发。
## 路由
使用 TanStack Router 文件路由系统,页面文件放在 `src/views/` 目录下:
- `__root.tsx` — 根路由(布局 + Framer Motion 过渡动画 + NProgress 进度条)
- `index.tsx` — 首页 `/`
- `about.tsx` — 关于页 `/about`
- `dashboard.tsx` — 仪表盘 `/dashboard`
- `settings.tsx` — 设置页 `/settings`
- `-not-found.tsx` — 404 页面
- `-forbidden.tsx` — 403 页面
- `-server-error.tsx` — 500 页面
新增页面只需在 `views/` 下创建文件,路由自动生成。文件名以 `-` 开头则不会被注册为路由(如 `-not-found.tsx`)。
```tsx
// src/views/hello.tsx
import { createFileRoute } from "@tanstack/react-router";
function HelloView() {
return Hello World
;
}
export const Route = createFileRoute("/hello")({
component: HelloView,
});
```
## 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `VITE_APP_TITLE` | 应用名称 | React Template |
| `VITE_SERVER_PORT` | 开发服务器端口 | 5173 |
| `VITE_SERVER_HOST` | 开发服务器主机 | localhost |
| `VITE_OPEN_BROWSER` | 启动时自动打开浏览器 | false |
| `VITE_PROXY_TARGET` | API 代理配置(JSON 数组) | `[["/api","http://localhost:3000"]]` |
| `VITE_PROXY_REWRITE` | 代理时是否重写路径前缀 | false |
| `VITE_API_BASE_URL` | 客户端 API 请求前缀 | /api |
| `VITE_API_BASE_URLS` | 多 base URL 客户端(JSON 对象) | - |
TypeScript 类型定义位于 `src/types/env.d.ts`。
## CI/CD
GitHub Actions 工作流(`.github/workflows/ci-cd.yml`)在 `main` 分支 push / PR 时自动触发:
| Job | 说明 |
|-----|------|
| Lint & Type Check | Oxlint 代码规范检查 |
| Unit Tests | Vitest 单元测试 + 覆盖率报告(上传 Codecov) |
| Build | 生产构建 + 产物大小分析 |
| Deploy | 仅 main 分支或 tag 推送时触发,发布 GitHub Release |
CI 环境使用 **pnpm 9** + **Node.js 22**,通过 `--frozen-lockfile` 确保依赖一致性。
## 构建优化
- **代码分割**:React、Zustand 等大型依赖拆分为独立 chunk
- **Gzip/Deflate 压缩**:构建产物自动生成 `.gz` 文件
- **Tree Shaking**:自动移除未使用代码
- **CSS 分割**:CSS 按需加载
- **Rolldown**:基于 Rust 的极速打包器
## 生产部署
```bash
pnpm build
# 将 dist/ 目录部署到服务器
```
建议 Nginx 配置静态压缩:
```nginx
gzip_static on;
```