本文档面向项目开发者,涵盖环境搭建、项目结构、开发规范、常用命令与扩展机制,帮助你快速上手并高效参与开发。
| 工具 | 版本要求 | 说明 |
|---|---|---|
| Node.js | >= 20.x | 建议使用 .nvmrc 统一版本 |
| pnpm | >= 8.x | 推荐通过 corepack enable 启用 |
| IDE | - | 推荐 Cursor / VSCode |
| 浏览器 | 现代浏览器 | Chrome 79+ / Firefox 78+ / Safari 14+ |
- ESLint
- Prettier - Code formatter
- stylelint
- TypeScript Importer
- Ant Design Snippets
git clone https://github.com/gvray/react-umi-admin.git
cd react-umi-admin
pnpm install
postinstall会自动执行umi setup,完成框架初始化。
项目根目录下按环境维护 .env 文件:
| 文件 | 环境 | 说明 |
|---|---|---|
.env.dev |
开发 | 默认使用 Mock,端口 9527 |
.env.staging |
测试 | 连接后端 nest-admin,端口 9528 |
.env.prod |
生产 | 生产环境配置,端口 9529 |
.env.example |
模板 | 环境变量模板,用于缺失检查 |
| 变量名 | 类型 | 说明 |
|---|---|---|
APP_ENV |
string | 当前环境标识:dev / staging / prod |
APP_API_URL |
string | API 请求前缀,如 /api |
APP_API_TIMEOUT |
number | 请求超时时间(ms) |
APP_API_TOKEN_KEY |
string | Token 存储 key |
APP_MOCK_ENABLED |
boolean | 是否启用 Mock 数据 |
APP_VERSION |
string | 应用版本号 |
APP_BUILD_TIME |
string | 构建时间 |
APP_CDN_URL |
string | CDN 地址(可选) |
APP_SENTRY_DSN |
string | Sentry DSN(可选) |
APP_TRACKING_ID |
string | 统计追踪 ID(可选) |
环境变量通过 scripts/load-env.ts 加载:
- 根据
--mode参数读取对应.env.{mode}文件 - 使用
dotenv注入到process.env - 通过
config/define.ts映射为全局常量(__APP_ENV__、__APP_API_URL__等) - 启动时自动打印环境变量表格,并与
.env.example对比检查缺失项
pnpm start # 等同于 pnpm start:dev
pnpm start:dev # 开发环境,端口 9527(Mock 模式)
pnpm start:staging # 测试环境,端口 9528(连接后端)
pnpm start:prod # 生产环境,端口 9529底层调用 tsx scripts/dev.ts --mode <env> --port <port>,支持参数:
--mode:环境名称,对应.env.{mode}和config/config.{mode}.ts--port:开发服务器端口--mock:手动覆盖 Mock 开关
pnpm build # 构建所有环境(dev + staging + prod)
pnpm build:dev # 仅构建 dev
pnpm build:staging # 仅构建 staging
pnpm build:prod # 仅构建 prod产物输出到 dist/{env}/ 目录。
pnpm lint # 运行 ESLint + Prettier + TSC 检查
pnpm lint:fix # ESLint 自动修复
pnpm lint:prettier # Prettier 格式化pnpm gen:api # 从 OpenAPI 文档生成 TypeScript 类型从后端 Swagger/OpenAPI JSON 自动生成 src/types/api.d.ts,包含:
- 所有 Schema → TypeScript interface
- Query 参数类型
- 通用分页 / 响应类型
pnpm analyze # Webpack Bundle 分析
pnpm clean # 清理 dist 和 node_modulesreact-umi-admin/
├── config/ # Umi 配置
│ ├── config.ts # 主配置(路由、主题、插件等)
│ ├── config.dev.ts # 开发环境覆盖配置
│ ├── config.staging.ts # 测试环境覆盖配置
│ ├── config.prod.ts # 生产环境覆盖配置
│ ├── define.ts # 全局常量定义(环境变量 → 编译常量)
│ ├── env.ts # 多环境扩展变量
│ ├── plugins.ts # Umi 插件列表
│ └── routes.ts # 路由配置
├── docs/ # 项目文档
├── mock/ # Mock 数据(Express 风格)
├── public/ # 静态资源
├── scripts/ # 构建 & 工具脚本
│ ├── dev.ts # 开发服务器启动脚本
│ ├── build.ts # 构建脚本
│ ├── load-env.ts # 环境变量加载器
│ └── gen-api-types.ts # OpenAPI 类型生成器
├── src/
│ ├── app.tsx # Umi 运行时配置(getInitialState)
│ ├── global.less # 全局样式
│ ├── global.ts # 全局脚本
│ ├── request.ts # 网络请求客户端初始化
│ ├── requestErrorConfig.ts # 请求错误处理配置
│ ├── themeConfig.ts # 主题配置
│ ├── components/ # 全局公共组件
│ │ ├── AuthButton/ # 权限按钮
│ │ ├── Charts/ # 图表组件
│ │ ├── ErrorBoundary/ # 全局错误边界
│ │ ├── IconSelector/ # 图标选择器
│ │ ├── NavigationProgress/# 路由进度条(NProgress)
│ │ ├── PageContainer/ # 页面容器(含 Helmet 标题管理)
│ │ ├── PermissionTree/ # 权限树
│ │ ├── StatusTag/ # 状态标签
│ │ ├── TablePro/ # 增强表格
│ │ └── index.ts # 统一导出
│ ├── constants/ # 全局常量
│ ├── hocs/ # 高阶组件(withAuth 等)
│ ├── hooks/ # 自定义 Hooks
│ │ ├── useAuth/ # 鉴权 Hook
│ │ ├── useConfig.ts # 系统配置 Hook
│ │ ├── useDict/ # 字典 Hook
│ │ ├── useRouteMeta/ # 路由元信息 Hook
│ │ ├── useTheme/ # 主题 Hook
│ │ ├── useThemeColor/ # 主题色 Hook
│ │ └── useThemeMode/ # 主题模式 Hook
│ ├── layouts/ # 布局组件
│ │ ├── index.tsx # 主布局(Header + Sider + Content)
│ │ └── components/ # 布局子组件(SideMenu、Logo、ThemeSetting)
│ ├── locales/ # 国际化资源
│ │ ├── zh-CN.ts # 中文
│ │ └── en-US.ts # 英文
│ ├── pages/ # 页面组件
│ ├── services/ # API 服务层
│ ├── stores/ # Zustand 状态管理
│ │ ├── useSettingsStore.ts
│ │ ├── useTabsStore.ts
│ │ └── useThemeStore.ts
│ ├── types/ # TypeScript 类型定义
│ ├── utils/ # 工具函数
│ └── wrappers/ # 路由包装器(RouteGuard)
└── package.json
路由定义在 config/routes.ts,采用 Umi 约定式配置:
{
path: '/system/user',
component: 'User',
meta: {
title: '用户管理',
permissions: ['system:user:view'],
},
}meta.title:页面标题,PageContainer组件通过useRouteTitle()读取并设置<title>meta.permissions:页面所需权限码,RouteGuard和withAuthHOC 会进行校验
所有需要鉴权的路由包裹在 @/wrappers/RouteGuard 中:
- 检查用户登录状态(Token 有效性)
- 未登录则重定向到
/login - 渲染
NavigationProgress(NProgress 路由进度条) - 渲染子路由
<Outlet />
- 页面级:
withAuthHOC 检查meta.permissions,无权限显示 403 - 按钮级:
<AuthButton>组件根据权限码控制按钮渲染 - 菜单级:动态菜单根据用户权限过滤
基于 @gvray/request(axios 封装)初始化,配置在 src/request.ts:
baseURL:由__APP_API_URL__全局常量控制timeout:由__APP_API_TIMEOUT__控制- 拦截器:在
src/requestErrorConfig.ts中配置请求/响应拦截
src/services/ 按业务模块组织 API 调用:
| 文件 | 模块 |
|---|---|
auth.ts |
登录鉴权 |
user.ts |
用户管理 |
role.ts |
角色管理 |
permission.ts |
权限管理 |
department.ts |
部门管理 |
position.ts |
岗位管理 |
dictionary.ts |
字典管理 |
config.ts |
系统配置 |
resource.ts |
资源管理 |
dashboard.ts |
仪表盘 |
loginLog.ts |
登录日志 |
operationLog.ts |
操作日志 |
Mock 文件位于 mock/ 目录,采用 Express 风格定义:
export default {
'POST /api/auth/login': async (req: Request, res: Response) => {
await sleep(800);
res.json({ success: true, code: 200, data: { ... } });
},
};.env.dev中APP_MOCK_ENABLED=true启用 Mock.env.staging中APP_MOCK_ENABLED=false关闭 Mock,连接真实后端- Mock 文件中不能使用
@/路径别名(Node.js 环境不支持),需用相对路径如../src/constants
当前 Mock 覆盖:登录、用户、角色、权限、部门、岗位、字典、资源、仪表盘等模块。如需全量真实数据,请启动后端 nest-admin。
项目使用 Zustand 作为轻量状态管理方案,Store 位于 src/stores/:
| Store | 职责 |
|---|---|
useSettingsStore.ts |
全局设置(侧边栏折叠等) |
useTabsStore.ts |
多标签页状态管理 |
useThemeStore.ts |
主题状态(暗黑/浅色/自定义色) |
同时通过 Umi 内置的 initialState + useModel 管理用户信息等全局初始数据。
- 主题配置入口:
src/themeConfig.ts - 运行时通过 Ant Design
ConfigProvider动态切换主题算法(亮色/暗色/紧凑) - 主题色通过
useThemeStore管理,支持实时切换
- 全局样式:
src/global.less - 页面样式:CSS Modules(
.less文件) - 组件样式:
styled-components(CSS-in-JS) - 主题变量:通过 Ant Design Token 系统统一管理
国际化资源位于 src/locales/:
src/locales/
├── zh-CN.ts # 中文入口
├── zh-CN/ # 中文子模块
├── en-US.ts # 英文入口
└── en-US/ # 英文子模块
通过 Umi 内置 locale 插件实现,默认语言为 zh-CN。使用 useIntl() 或 <FormattedMessage> 在组件中引用翻译。
所有公共组件通过 src/components/index.ts 统一导出:
| 组件 | 说明 |
|---|---|
PageContainer |
页面容器,集成权限校验 + Helmet 标题 |
ErrorBoundary |
全局错误边界,捕获渲染异常 |
NavigationProgress |
路由切换进度条(NProgress) |
AuthButton |
权限按钮,根据权限码控制渲染 |
TablePro |
增强表格组件 |
Charts |
ECharts 图表封装 |
IconSelector |
Ant Design 图标选择器 |
PermissionTree |
权限树组件 |
StatusTag |
状态标签(启用/禁用等) |
DateTimeFormat |
日期时间格式化组件 |
AntIcon |
动态 Ant Design 图标渲染 |
通过 src/hooks/index.ts 统一导出:
| Hook | 说明 |
|---|---|
useAuth |
登录鉴权逻辑 |
useAppTheme |
主题管理 |
useThemeMode |
主题模式切换 |
useRouteMeta |
获取当前路由元信息 |
useRouteTitle |
获取当前路由标题 |
useRoutePermissions |
获取当前路由权限码 |
useConfigValue |
读取系统配置值 |
useConfigsByGroup |
按分组读取配置 |
useConfigsByType |
按类型读取配置 |
useEnabledConfigs |
读取已启用配置 |
useConfigCache |
配置缓存 |
useConfigValidation |
配置校验 |
- 创建页面组件:在
src/pages/下新建目录和index.tsx - 注册路由:在
config/routes.ts中添加路由配置,设置meta.title和meta.permissions - 添加 API 服务:在
src/services/中新建对应服务文件 - 添加 Mock(可选):在
mock/中添加对应 Mock 数据 - 添加菜单:在后端或 Mock 中注册菜单项
- 使用 PageContainer:页面根组件使用
<PageContainer>包裹,自动获得权限校验和标题管理
import { PageContainer } from '@/components';
const MyPage: React.FC = () => {
return <PageContainer>{/* 页面内容 */}</PageContainer>;
};
export default MyPage;- 环境变量检查:启动时控制台会打印环境变量表格,确认配置正确
- Mock 调试:Mock 文件修改后自动热更新,无需重启
- TypeScript 检查:
npx tsc --noEmit快速检查类型错误 - Bundle 分析:
pnpm analyze查看打包体积分布 - React DevTools:推荐安装 React Developer Tools 浏览器扩展
- 网络请求:所有请求错误会通过
requestErrorConfig.ts统一处理并弹出提示
- Mock 文件中不能使用
@/别名:Mock 运行在 Node.js 环境,需使用相对路径(如../src/constants) - 环境变量必须以
APP_开头:非APP_前缀的变量不会被 dotenv 加载到 define 中 - 路由
meta是自定义扩展:Umi 原生不支持meta,通过useRouteMetaHook 解析 - pnpm 严格模式:项目使用 pnpm,不要混用 npm/yarn 安装依赖
- Node.js 版本:确保使用 Node.js 20+,低版本可能导致构建脚本异常
| 层 | 作用 | 命名关注点 |
|---|---|---|
| Service | 调用后端 API,REST 风格 | 用后端 API 风格:createUser / updateUser / deleteUser / queryUsersList |
| Model / Store | 管理前端状态、业务逻辑 | 用业务动作语义:addUser / editUser / removeUser / fetchUsersList |
| UI / Component | 页面事件触发、Prop 绑定 | handle + Model 方法:handleAddUser / handleUpdateUser / handleDeleteUser |
- feature/* → 每个新功能或 bug 修复
- develop → 测试环境,集成所有 feature
- release/* → 准备发版,冻结功能,做最终测试
- main → 生产环境,始终稳定
- hotfix/* → 紧急修复生产环境 bug