可扩展的 React 项目文件夹结构

简介: 强烈推荐!

<!DOCTYPE html>

在构建小型应用时,几乎任何结构都能跑得起来。但一旦项目开始增长——组件变多、业务逻辑复杂、接入 API、引入 state ——如果文件夹结构一开始没想清楚,很快就会陷入混乱。

在这篇文章中,我会分享一个我在 2025 年个人常用、并且非常认可的现代化、可扩展 React 文件夹结构。无论你是在做个人项目,还是打算扩展一个企业级应用,这套结构都能帮助你保持组织清晰、一致,并且心态稳定。


为什么文件夹结构这么重要

在开始之前,先问一句——为什么要在意这些?

因为一个干净的结构可以:

  • 让新成员(或者未来的你)更容易上手:明确职责边界(UI、逻辑、数据获取)。
  • 明确职责边界(UI、逻辑、数据获取):减少 bug 和重复代码。
  • 减少 bug 和重复代码:鼓励可扩展性和模块化。

结构设计(清晰、可扩展、对开发者友好)

以清晰度为核心构建

.
├── eslint.config.js
├── index.html
├── package.json
├── public
│ └── vite.svg
├── README.md
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets # 图片,字体,图标等等
│ │ └── react.svg
│ ├── components # 可重复使用的纯 UI 组件
│ │ └── Button
│ │ ├── Button.module.css
│ │ ├── Button.test.ts
│ │ └── index.tsx
│ ├── features # 业务逻辑和特定功能相关
│ │ └── auth
│ │ ├── AuthPage.tsx
│ │ ├── components
│ │ ├── hooks
│ │ └── services
│ ├── hooks # 自定义 hooks
│ ├── layouts # 可重复调用的Layout封装(DashBoradLayout、AuthLayout)
│ ├── pages # 与路由结构保持一致(映射到routes)
│ ├── routes # 路由的集中配置(React Router)
│ ├── services # API调用
│ ├── store # 全局状态
│ ├── types # 类型定义
│ ├── utils # 工具函数、常量、帮助文件等
│ ├── config # 环境配置、主题、应用设置等等
│ ├── index.css
│ └── main.tsx
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts

1. Components vs. Features

  • 使用 /components 存放 纯 UI 组件——无状态、可复用、跨应用使用(例如:Button、Input、Modal)。
  • 使用 /features 存放 业务逻辑和特定功能相关的文件。每个领域(如 auth 、 chat 、 profile )都有自己的文件夹,内部通常包含:
    • components/
    • services/
    • hooks/
    • pages/ 甚至可以有自己的 state( store/ )

这种方式可以让逻辑就近收敛,避免文件膨胀或混乱的全局 state。


2. Pages = Routes

让 /pages 文件夹与路由结构保持一致。

每一个 page 对应一个 route,内部可以自由引入 feature 模块或 layout。


3. 集中的 Services 层

API 调用不应该写在组件里。

使用 /services 文件夹来统一定义所有后端请求。例如:

export const login = (credentials) => axios.post('/login', credentials)

让 UI 专注于 UI。它应该在 /services/auth.js 。

这样当后端接口发生变化时,你只需要修改一个地方。


4. 全局 Store?只在真正需要时才用

不要从第一天就上全局 state。

优先把 state 保持在 feature 内部。只有当 state确实需要在距离很远的组件之间共享时,才考虑 Redux、Zustand 或 Context API。


5. Hooks:无痛复用逻辑

自定义 hooks 是救命稻草。

无论是 useAuth 、 useDebounce 还是 useForm ,把它们放在统一的 /hooks 文件夹里,可以在不复制代码的情况下复用逻辑。

它们尤其适合处理:

  • API fetching、表单处理
  • 表单处理、动画或副作用
  • 动画或副作用、LocalStorage / session 相关逻辑

没有一种文件夹结构可以适用于所有场景。但我在这里分享的这套布局,已经在个人项目、团队项目以及 hackathon 中被反复验证,具备良好的扩展性。

保持模块化。
保持干净。
保持清晰。


RECOMMEND


推荐阅读
相关文章
|
3月前
|
前端开发 JavaScript API
前端组件库——shadcn/ui知识点大全(一)
教程来源 http://uklgy.cn/ shadcn/ui 是2026年React生态引领变革的UI方案:不提供npm黑盒包,而是通过CLI将可定制、带完整类型与无障碍支持的组件源码(如`button.tsx`)直接复制到项目中。基于Radix UI、Tailwind CSS与自研CLI,赋予开发者对样式、行为与API的完全控制权。GitHub星标超11万,周下载近200万。
|
6月前
|
JSON 数据可视化 API
实用程序:解放双手!Python 打造 PDF 手写模拟器,轻松搞定手写作业
一款基于Python的PDF手写模拟器,可批量将文字以逼真手写形式填入PDF指定区域。支持中英文独立配置、手写扰动效果调节、模板复用与实时预览,告别手动抄写。开源免费,操作简便,学生党必备!GitHub已开源,欢迎Star!
590 0
|
6月前
|
存储 编解码 Cloud Native
全链路解析:基于云原生架构的 Bilibili 视频下载引擎实现
本文深入解析基于云原生架构的B站视频下载引擎,涵盖DASH协议分析、音视频分片下载、FFmpeg无损合成及阿里云Serverless部署。结合异步任务编排、OSS存储与反爬策略,实现高效、合规的全链路流媒体解析,适用于离线学习与弱网播放场景。(238字)
|
存储 编解码 调度
剖析ffmpeg视频解码播放:时间戳的处理
剖析ffmpeg视频解码播放:时间戳的处理
2054 0
|
11月前
|
缓存 API 网络架构
DRF视图详解:从基础视图到通用视图实践指南
在 Django REST Framework (DRF) 开发中,视图是处理 HTTP 请求并返回响应的核心组件。DRF 提供了多种视图类型,从基础的 APIView 到功能丰富的通用视图。本文将详细介绍视图的演进过程,帮助理解不同视图的设计思想和使用方法。
380 0
|
9月前
|
安全 API
LlamaIndex检索调优实战:分块、HyDE、压缩等8个提效方法快速改善答案质量
本文总结提升RAG检索质量的八大实用技巧:语义分块、混合检索、重排序、HyDE查询生成、上下文压缩、元数据过滤、自适应k值等,结合LlamaIndex实践,有效解决幻觉、上下文错位等问题,显著提升准确率与可引用性。
865 8
|
8月前
|
人工智能 自然语言处理 搜索推荐
教育行业Agent案例全解析:覆盖K12、高教、职教的落地实践与标杆范本
Salesforce调研显示,77%学生愿用AIAgent解决校园事务,83%管理者期待减负。本文基于真实案例,系统梳理K12、高校、职教三大场景中智能体在教学、管理、服务中的创新应用,揭示AI如何重塑教育未来。
1597 4
|
存储 安全 Linux
|
人工智能 并行计算 搜索推荐
SPAR3D:一张图片就能生成3D模型,每个物体的重建时间仅需0.7秒!
SPAR3D 是由 Stability AI 和伊利诺伊大学香槟分校推出的先进单图生成3D模型方法,支持快速推理与用户交互式编辑,适用于多种3D建模场景。
2286 30
SPAR3D:一张图片就能生成3D模型,每个物体的重建时间仅需0.7秒!
阿里云实名认证api接口怎么调用
当我们注册一个购物网站,或者下载某个游戏,很多地方都需要做实名认证。那么作为购物网站,或者游戏公司,怎么才能判断客户提供的身份证号码是否真实呢?游戏玩家越来越多,我们可能人工去审核这个人提供个的身份证号码是否属实,或者是否是真人。根据国家规定,我们很多游戏都要对未成年游戏时长进行控制,也就是通常大家所谓的游戏防沉迷系统。我们只要把那些进行实名认证玩家的年龄给摘出来以后,就可以判断其是否成年。
阿里云实名认证api接口怎么调用