React 大型项目目录骨架

React 大型项目目录骨架

前置:React 数据请求:TanStack Query

目标:建立可扩展的目录直觉:features / pages / shared,知道新代码该往哪放。

引言

入门 demo 往往是:

text 复制代码
src/
  App.tsx
  components/
    Header.tsx
    TodoList.tsx
    UserCard.tsx
    ...

项目变大以后,问题不是「React 不会写」,而是:

  • 改一个业务,要在 components/ 里翻半天才找到相关文件
  • 首页、登录、任务模块的组件混在一起,互相乱引用
  • 新人不知道「这个按钮 / 这个 hook 该放哪」

本篇不追完美架构,只给一套够用、可长 的起步骨架:按 业务(feature) 内聚,页面保持薄,跨业务的东西进 shared。

本篇 demo/ 已按此拆了一版可点的迷你应用:首页 + 任务模块 + 共享按钮。

目录示意

推荐起步结构:

text 复制代码
src/
  app/          # 可选:全局 provider、路由表
  pages/        # 路由级页面(薄)
  features/     # 按业务内聚(tasks、auth...)
  shared/       # 跨业务 UI / utils

动手

完整代码:react2/08-large-project/demo

bash 复制代码
cd react2/08-large-project/demo
npm install
npm run dev
  • / → pages/HomePage
  • /tasks → features/tasks/TasksPage(用 shared/Button)

点顶栏「首页 / 任务」,感受「路由页」和「业务模块」是怎么分开的。


1. 为什么不要一股脑塞进 components/

做法 短期 项目长大以后
全部丢 components/ 好找文件名 业务边界糊掉,互相 import 成蜘蛛网
按 UI 类型分(buttons/、forms/) 看起来整齐 改「任务」仍要跨很多目录
按 feature 分(features/tasks/) 多建一层目录 相关代码挨在一起,改一块少翻别处

直觉:经常一起改的,放一起 。

「任务列表 + 加任务逻辑 + 任务相关 hook」属于 features/tasks;「全站都能用的按钮」才进 shared。


2. 四层分别干什么

pages/:路由级页面(尽量薄)

对应 URL 入口,少写业务细节,多做组装:

tsx 复制代码
// pages/HomePage.tsx
import { Link } from 'react-router-dom'

export function HomePage() {
  return (
    <section className="panel">
      <h1>首页</h1>
      <p>
        大型项目按 <code>features / pages / shared</code> 拆目录,功能内聚、页面薄。
      </p>
      <Link to="/tasks">进入任务模块 →</Link>
    </section>
  )
}

约定:

  • 一个路由 ≈ 一个 page(或 page 再调 feature)
  • page 里少堆 useState / 复杂请求;重逻辑下沉到 features/

features/:按业务内聚

一个业务一块地:页面、组件、hooks、API 都可以放在同一 feature 下。

tsx 复制代码
// features/tasks/TasksPage.tsx
import { useState } from 'react'
import { Button } from '../../shared/Button'

export function TasksPage() {
  const [items, setItems] = useState(['搭建目录', '拆分 feature', '接入路由'])

  return (
    <section className="panel">
      <h1>任务 Feature</h1>
      <ul>
        {items.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
      <Button
        onClick={() =>
          setItems((list) => [...list, `新任务 ${list.length + 1}`])
        }
      >
        添加任务
      </Button>
    </section>
  )
}

长大以后可以继续往下拆,例如:

text 复制代码
features/tasks/
  TasksPage.tsx
  components/TaskItem.tsx
  hooks/useTasks.ts
  api.ts

先别过度拆;文件变多、找起来费劲时再拆。

shared/:跨业务复用

只放「两个及以上 feature 都会用」的东西:通用 Button、布局、日期格式化、fetch 封装等。

tsx 复制代码
// shared/Button.tsx
import type { ButtonHTMLAttributes, ReactNode } from 'react'

type Props = ButtonHTMLAttributes<HTMLButtonElement> & {
  children: ReactNode
}

export function Button({ children, ...rest }: Props) {
  return (
    <button type="button" className="btn" {...rest}>
      {children}
    </button>
  )
}

判断口诀:

  • 只有任务模块用 → 留在 features/tasks
  • 首页、任务、设置都会用 → shared

app/(可选):全局装配

Provider(QueryClient、主题)、路由表、鉴权壳子等「应用级胶水」可以放这里。

本 demo 体量小,路由直接写在 App.tsx,没有单独建 app/,这是刻意简化。


3. 路由怎么把它们串起来

tsx 复制代码
// App.tsx
import { BrowserRouter, Link, Route, Routes } from 'react-router-dom'
import { TasksPage } from './features/tasks/TasksPage'
import { HomePage } from './pages/HomePage'

export default function App() {
  return (
    <BrowserRouter>
      <div className="shell">
        <header className="top">
          <strong>LargeApp 骨架</strong>
          <nav>
            <Link to="/">首页</Link>
            <Link to="/tasks">任务</Link>
          </nav>
        </header>
        <main>
          <Routes>
            <Route path="/" element={<HomePage />} />
            <Route path="/tasks" element={<TasksPage />} />
          </Routes>
        </main>
      </div>
    </BrowserRouter>
  )
}

依赖方向可以记成:

text 复制代码
App(路由 / 壳)
  → pages / features(页面与业务)
    → shared(通用 UI / utils)

尽量避免:shared 去 import 某个 features/xxx(通用层不应依赖具体业务)。


4. 对照表

目录 回答的问题 demo 里有什么
pages/ 这个 URL 入口是谁? HomePage
features/tasks/ 任务业务的代码在哪? TasksPage + 本地 state
shared/ 全站通用控件? Button
App.tsx 壳子 + 路由表 顶栏 + /、/tasks
新增需求 优先落点
新路由「关于页」 pages/AboutPage + 挂一条 Route
任务详情、任务筛选 features/tasks/ 里加文件
全站统一的 Input shared/Input.tsx
登录 / 权限一整块 features/auth/(不要散到各处)

5. 常见坑

做法 问题
一切仍丢 components/ 目录「看起来有结构」,业务边界没有
page 里写满请求与业务规则 页面变胖,难复用、难测
feature 之间互相乱引用 tasks ↔ auth 缠死,拆不动
过早建 entities / widgets 七层 小项目被架构压垮;先 features + shared 够用
把只属于任务的按钮放进 shared shared 膨胀成杂物间

demo 在练什么

  1. 用 pages / features / shared 看清三层职责
  2. 路由只负责挂载,业务状态留在 feature 内
  3. feature 通过 shared/Button 复用通用 UI,而不是复制一份样式按钮

自己改一改:再加一个 features/notes/,挂 /notes;或把任务列表拆成 TaskItem.tsx 仍放在 features/tasks/ 下。


运行截图

相关推荐
JudithHuang1 小时前
React 条件渲染与 JSX 进阶
react.js
JudithHuang2 小时前
React 常用 Hooks
前端·react.js·前端框架
用户298698530147 小时前
在 React 中使用 JavaScript 将 HTML 转换为 PDF
javascript·react.js·html
JudithHuang7 小时前
React 数据请求:TanStack Query
前端·react.js·前端框架
JudithHuang9 小时前
React 路由:React Router
前端·react.js·前端框架
光影少年9 小时前
RN与Flutter架构区别
前端·flutter·react native·react.js·架构·node.js
FungLeo18 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
Mr_Mao1 天前
告别选型困难!集 VueUse、ahooks、Mantine 于一身:286 个 Hook 的 ReaUse 来了
前端·javascript·react.js
智鸟科技GemeOpen开发者智能设备1 天前
智能插座二次开发如何接入Home Assistant,从零开始完整工程实现(Python+React)
开发语言·python·物联网·react.js·智能家居