人人都会AI编程

27.3 大型 React 项目架构设计

更新时间:2026-07-11

当项目从一个简单的页面迭代到几十个模块、上百个页面,由十人以上的团队协作开发时,架构设计直接决定了项目的可维护性、可扩展性和开发效率。本节将拆解大型 React 项目架构设计的核心要点,提供可直接落地的实践方案。

27.3.1 大型项目的核心挑战

  • 代码量膨胀:组件、状态、逻辑散落各处,耦合严重,牵一发动全身。
  • 多人协作冲突:不同开发者修改同一文件,命名冲突、风格不一致。
  • 业务域交错:订单模块、用户模块、权限模块各自独立,但经常需要共享数据或组件。
  • 性能与加载效率:首屏加载慢、代码冗余、重复渲染。
  • 可测试性与质量保障:复杂逻辑难以编写单元测试,回归测试成本高。

应对这些挑战,需要一套分层清晰、边界明确的架构体系。

27.3.2 模块分层架构

借鉴后端分层思想,前端也可以按“关注点分离”的原则进行分层,常见为三层或四层架构。

推荐分层模型:

展示层(Presentation)  →  领域层(Domain)  →  基础设施层(Infrastructure)
  • 展示层:纯 UI 组件,只负责渲染和交互,不包含业务逻辑。例如通用 Button、Modal,或特定业务的 UserCard、OrderItem。
  • 领域层:业务逻辑封装为自定义 Hooks(如 useOrderDetail)、领域模型函数(如 calcDiscount),以及领域状态管理(如 orderStore)。领域层决定“能做什么”和“数据怎么流转”。
  • 基础设施层:提供通用技术能力,如 HTTP 请求封装、日期格式化、本地存储、日志上报、第三方 SDK 初始化等。该层与业务无关,可在不同项目中复用。

目录结构示例:

src/
├── infrastructure/          # 基础设施层
│   ├── http/                # Axios 封装、拦截器
│   ├── storage/             # localStorage/sessionStorage 封装
│   ├── logger/              # 日志收集
│   └── utils/               # 纯工具函数(lodash 等)
├── domain/                  # 领域层(按业务域拆分)
│   ├── order/
│   │   ├── hooks/           # useOrderList, useOrderDetail
│   │   ├── services/        # 领域服务:orderApi, orderReducer
│   │   └── types/           # 领域模型类型
│   └── user/
├── presentation/            # 展示层
│   ├── components/          # 通用 UI 组件
│   │   ├── Button/
│   │   ├── Table/
│   │   └── Modal/
│   ├── features/            # 业务功能组件(由领域组件 + 通用组件拼装)
│   │   ├── OrderList/
│   │   └── UserProfile/
│   └── layouts/             # 布局组件(Header、Sidebar、MainContent)
├── routes/                  # 路由配置
├── store/                   # 全局状态(跨业务域共享)
└── App.tsx

这种分层的好处是:依赖方向自上而下,展示层可以依赖领域层和基础设施层,但基础设施层不能反向依赖业务。当业务变动时,只需修改领域层,展示层保持稳定。

27.3.3 业务域拆分

大型应用往往包含多个独立的业务线,如电商平台的“商品”“订单”“用户”“营销”等。我们将每个业务域作为一个独立的功能模块来组织,模块之间通过明确的接口通信,避免混乱耦合。

拆分原则:

  • 高内聚:一个模块内部的所有代码(组件、Hooks、API、类型)共同完成该领域的功能。
  • 低耦合:模块间的依赖仅限于稳定的接口(如共享的组件库、公共状态、特定服务函数),而不是直接引用对方模块的内部文件。
  • 可独立交付:理想情况下,一个业务域可以独立开发、测试和部署(如果配合微前端则更彻底)。

模块内部结构:

domain/order/
├── components/        # 仅本模块使用的展示组件
├── hooks/             # 业务逻辑 Hooks
├── services/          # 数据获取与处理
├── types/             # 订单相关的 TypeScript 接口
└── index.ts           # 对外暴露的公共接口(如少数共享组件或 Hooks)

模块间通信方式:

  1. 通过 URL 参数/路由传递:例如从订单列表点击进入订单详情,通过路由参数传递 orderId
  2. 通过全局状态:如用户登录信息、全局主题等,由 store/user 模块管理,其他模块读取。
  3. 通过事件总线(不推荐)或回调函数:少量跨模块交互可使用 Context + 回调,避免滥用全局状态。
  4. 共享领域服务:例如 userService.getCurrentUser(),可被多个领域模块调用,但不直接耦合 UI。

27.3.4 组件库设计与公共能力沉淀

大型项目必然沉淀出大量可复用组件和基础能力,将它们抽象为“组件库”或“通用工具包”可以大幅提升效率。

分层设计组件:

  • 基础组件(Primitives):Button、Input、Modal、Tooltip 等,与业务完全无关,追求通用性和易用性。可参考 Ant Design 的设计规范自研,或直接选型成熟 UI 库二次封装。
  • 业务组件(Widgets):结合基础组件与特定领域产生的复合组件,例如 UserSelector(带搜索的选人弹窗)、OrderStatusTagMoneyDisplay。它们对业务有语意,但跨模块复用。
  • 页面模板(Templates):典型的列表页、详情页、表单页模板,固化交互模式。

组件开发规范:

  • 每个组件独立目录,包含 index.tsxtypes.tsstyle.module.css(或 styled-components)、tests
  • 使用 TypeScript 定义清晰的 Props 接口,并导出类型供使用者引用。
  • 组件应默认支持 ref 转发(如有必要),通过 React.forwardRef 暴露底层 DOM。
  • 使用 Storybook 构建组件文档和演示,方便跨团队共享和调试。

公共能力沉淀清单:

  • 自定义 Hooks 库:如 useRequest(数据请求)、usePaginationusePermissionuseForm(集成 React Hook Form)、useDebounce 等,统一业务逻辑的调用方式。
  • 工具函数集:日期格式化、数字格式化、权限判断、埋点上报等,集中管理避免到处复制。
  • 请求层抽象:统一错误处理、Token 刷新、Loading 状态、接口类型,让开发者专注 api.order.list() 而不关心 HTTP 细节。
  • 状态管理模块:将全局状态按领域划分为 store slices(Zustand/Redux 均可),提供清晰的 action 和 selector。

27.3.5 路由与权限体系

大型项目的路由往往复杂且动态,需与权限深度整合。

路由模块设计:

// routes/index.tsx
const dashboardRoutes = { ... };
const orderRoutes = { ... };
const settingsRoutes = { ... };

// 合并并根据权限过滤
const protectedRoutes = [dashboardRoutes, orderRoutes, settingsRoutes];

权限控制方案:

  • 路由权限:在路由配置中定义 permission 字段,渲染前检查用户是否拥有该权限。可使用高阶组件或自定义 usePermission Hook 包裹。
  • 组件级权限:按钮、菜单项等细微粒度的权限控制,通过 if (hasPermission('order:delete')) 包裹。
  • 菜单权限:后台管理系统的菜单通常与路由一一对应,根据用户权限动态生成可见菜单。

示例:

// components/AuthRoute.tsx
function AuthRoute({ children, permission }) {
  const hasAccess = usePermission(permission);
  if (!hasAccess) return <Navigate to="/403" replace />;
  return children;
}

27.3.6 状态管理策略

除了局部组件状态,大型应用还需要管理跨模块共享的状态,需要分层使用:

  • UI 状态:如弹窗的显隐、表单的临时数据,使用组件内 useStateuseReducer
  • 服务器缓存状态:使用 TanStack Query 或 SWR,将获取的数据自动缓存、同步,避免手动管理 loading/error。
  • 全局业务状态:如用户信息、全局配置,使用 Zustand 或 Redux Toolkit,按领域拆分 slice。
  • URL 状态:如搜索条件、分页信息,始终存储在 URL query 上,保证分享和刷新后可恢复。

状态选择原则是最小暴露原则:一个状态的作用域越小越好,能用组件内部状态就不提升,能用 Context 就不上全局 store。

27.3.7 构建与部署优化

大型项目构建时间和打包体积是必须关注的指标。

构建优化:

  • 使用 Vite 或 Turbopack 等高速构建工具,利用 ESM 按需编译。
  • 代码分割:路由级懒加载(React.lazy),合理拆分 vendor chunks。
  • 依赖外置:将 React、ReactDOM 等大型库通过 CDN 引入(可选,需权衡缓存与加载)。
  • 图片与字体优化:使用压缩、WebP 格式、按需加载。

部署策略:

  • 多环境隔离:dev、test、staging、production 环境变量区分。
  • CI/CD 流水线集成:代码质量检查(ESLint + TypeScript + 单测) → 构建 → 部署到 CDN 或静态服务器。
  • 微前端部署:如果采用 Module Federation 或 qiankun,各子应用可独立部署和灰度发布。

27.3.8 工程规范与质量保障

大型项目必须建立统一的规范和自动化校验,否则质量无从谈起。

  • 代码规范:ESLint + Prettier 统一代码风格,配置文件纳入版本管理。
  • Git 提交规范:使用 Commitlint + Husky 强制 commit message 格式,可自动生成 changelog。
  • 类型安全:全量开启 TypeScript strict 模式,禁止滥用 any
  • 测试策略
  • 单元测试:核心工具函数、复杂 Hooks、关键业务逻辑覆盖率 > 80%。
  • 组件测试:使用 React Testing Library 测试用户交互行为。
  • E2E 测试:Cypress/Playwright 保障核心业务流程(如登录、下单)可用。
  • 监控与日志:接入前端监控系统(Sentry 等),收集错误和性能数据,及时发现问题。

27.3.9 一个真实项目的落地目录结构

以下是一个典型的电商后台管理项目目录结构,可作为参考起点:

project/
├── public/
├── src/
│   ├── infrastructure/          # 基础设施
│   │   ├── http/                # axios 实例、拦截器
│   │   ├── storage/             # 缓存工具
│   │   ├── utils/               # 通用工具(日期、数字格式化……)
│   │   └── logger/              # 日志与埋点
│   ├── domain/                  # 业务领域
│   │   ├── auth/                # 登录、权限
│   │   │   ├── hooks/           # useLogin, usePermission
│   │   │   ├── services/        # authApi.ts
│   │   │   └── types/
│   │   ├── order/
│   │   └── product/
│   ├── presentation/            # 展示层
│   │   ├── base/                # 基础 UI 组件(Button, Modal……)
│   │   ├── business/            # 业务组件(OrderCard, ProductSelector……)
│   │   └── layout/              # 布局(AdminLayout, AuthLayout)
│   ├── routes/                  # 路由配置、权限守卫
│   │   ├── index.tsx
│   │   └── routeConfig.ts
│   ├── store/                   # 全局状态(Zustand/Redux)
│   │   ├── userStore.ts
│   │   └── appStore.ts
│   ├── hooks/                   # 全局共享 Hooks(useDebounce, usePagination...)
│   ├── types/                   # 全局类型定义
│   ├── App.tsx
│   └── main.tsx
├── .eslintrc.cjs
├── .prettierrc
├── tsconfig.json
├── vite.config.ts
└── package.json

这个结构完美地体现了模块分层、业务域拆分和公共能力沉淀。实际项目中,可根据团队规模和业务复杂度灵活调整,但核心原则不变:边界清晰、依赖单向、高内聚低耦合


通过上述架构设计,一个大型 React 项目能够在保持高开发效率的同时,具备优秀的可维护性与可扩展性。架构不是固定的教条,而应随着项目演进持续优化,但分层的思想和关注点分离的原则是长期有效的基石。