应根据项目规模选择目录结构:单页应用用CRA默认结构,多端或多团队协作必须采用Monorepo+功能域划分,根目录设apps、packages、.cursor,React项目内按app/features/shared/types四层组织,features需闭环,shared禁放业务逻辑,命名与导出须规范。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

在 Cursor 中开发 React 项目时,目录结构混乱会导致 AI 辅助编码频繁错引文件、类型不一致、跨组件复用困难,甚至生成重复逻辑或错误的 API 调用路径。
先明确项目规模再选结构
单页应用(如内部工具、营销落地页)直接用 Create React App 默认结构起步即可:src/components、src/pages、src/utils 三层分法够用。但一旦涉及多端(H5 + PC + 小程序)、多团队协作或需共享类型/请求封装,就必须升级为 Monorepo + 功能域划分结构——否则 Cursor 很容易把 mobile-h5 的接口定义当成 backend 的 DTO 去生成校验逻辑。
这一步不能跳过。你得先判断:当前项目未来三个月会不会新增第二个前端?有没有后端同事要共用同一套 request 封装?如果有,立刻按 Monorepo 规划。
推荐的 Monorepo 目录骨架
根目录下建三个核心目录:【apps】放可独立运行的项目,【packages】放跨项目共享代码,【.cursor】放规则配置。其他如 docs、docker、scripts 按需添加,不强求。
apps/backend → FastAPI 后端服务
apps/admin-web → Vue3 管理后台
apps/mobile-h5 → Vue3 H5 移动端
apps/desktop-web → React PC 端(即你当前正在开发的项目)
packages/api-types → TypeScript 接口定义(backend 和所有前端都 import 这里)
packages/request → axios 统一封装(含拦截器、错误码映射)
packages/ui-components → 基于 Ant Design 二次封装的 Button、Table、Form 等
.cursor/rules/ → 放 project.mdc(约束 React 工程标准)和 typescript.mdc(强制类型检查策略)
React 项目内部(apps/desktop-web)怎么组织
不要照搬老式 src/components/src/pages/src/utils 三件套。Cursor 对“页面级入口”和“业务模块边界”极其敏感,必须显式隔离。
第一步:src 下只保留四个顶层目录 —— 【app】(路由入口与全局 Provider)、【features】(按业务域切分)、【shared】(跨 feature 复用能力)、【types】(仅导出类型,不放实现)。
第二步:features 下每个子目录必须是完整闭环。例如 features/user-management/ 包含:
• api/(仅封装本域请求,useUserList、useUpdateUser)
• components/(仅本域 UI 组件,UserCard、UserSearchBar)
• hooks/(仅本域自定义 hook,useUserPermissions)
• index.tsx(导出本域默认页面组件,供 app/router.tsx 引入)
第三步:shared 目录禁止出现业务逻辑。它只允许放:
• components/(Button、Modal、EmptyState 等无状态基础组件)
• hooks/(useDebounce、useWindowSize)
• utils/(formatDate、isEmail)
• constants/(STATUS_CODES、ROLES)
• types/(BaseResponse
注意:shared/types 不等于 packages/api-types。前者是通用类型(如分页结构),后者是真实 API 契约(LoginRequest/LoginResponse)。混淆这两者会让 Cursor 在生成 login 表单校验逻辑时,误把 BaseResponse 当成后端返回体去解构 data 字段。
关键文件命名与导出规范
每个 features/xxx/index.tsx 必须默认导出一个命名明确的页面组件,比如 export default UserManagementPage;不能导出 function UserManagement() {}。
packages/api-types/index.ts 必须用 export * from './auth'; export * from './user'; 方式聚合,且每个子文件只 export interface 或 type,禁止 export const 或 function。
apps/desktop-web/src/app/router.tsx 中的 route path 必须与 features 目录名严格对应:path: '/users' → lazy(() => import('../features/user-management'))。
这一步做完,Cursor 就能准确识别 “/users 页面由 user-management feature 提供”,而不是从 20 个散落的 components 里猜哪个是主页面。











