Expo(React Native)项目行业主流目录结构及架构选型咨询
作为常年在Expo/React Native项目里摸爬滚打的老开发,我太懂你这种项目变大后目录乱成一锅粥的焦虑了!结合我带过的几个中型项目经验,给你梳理下行业里最实用的目录结构和架构选型,完全贴合你要的可维护、易扩展、团队协作友好这些核心需求~
一、传统层式(Type-Based)目录结构:新手友好,小项目首选
这个结构是新手入门最常见的,完全按代码的「类型」分类,直观好懂,适合刚起步的小项目或1-2人的小团队。
目录树示例
your-expo-app/ ├── app/ # Expo Router 核心路由目录(新版路由必用) │ ├── (tabs)/ # 底部标签页路由组 │ │ ├── home.tsx │ │ ├── profile.tsx │ │ └── _layout.tsx │ ├── +not-found.tsx │ └── _layout.tsx ├── assets/ # 静态资源统一存放 │ ├── images/ │ ├── fonts/ │ └── icons/ ├── components/ # 全局通用组件(和业务无关,比如按钮、输入框) │ ├── Button.tsx │ ├── Input.tsx │ └── Card.tsx ├── hooks/ # 全局通用自定义Hook(比如防抖、本地存储) │ ├── useDebounce.ts │ ├── useLocalStorage.ts │ └── useKeyboardHeight.ts ├── services/ # API、第三方服务封装 │ ├── api/ │ │ ├── client.ts # Axios/Fetch实例封装 │ │ ├── auth.ts # 鉴权接口 │ │ └── posts.ts # 帖子接口 │ └── pushNotification.ts # 推送服务 ├── store/ # 状态管理(Redux Toolkit/Zustand/Jotai) │ ├── slices/ │ │ ├── authSlice.ts │ │ └── postsSlice.ts │ └── store.ts ├── utils/ # 通用工具函数(格式化、验证、常量) │ ├── formatters.ts │ ├── validators.ts │ └── constants.ts ├── types/ # TypeScript全局类型定义 │ ├── auth.ts │ ├── posts.ts │ └── index.ts └── package.json
为什么用这个结构?
- 分类逻辑简单,新人上手快,不用花时间理解业务边界
- 通用模块集中管理,避免跨页面重复造轮子
- 符合大多数React项目的初始直觉,检索代码效率高
优缺点
✅ 优点
- 学习曲线平缓,小型项目开发效率拉满
- 通用组件/工具复用成本低
- 类型划分明确,找文件不用瞎逛
❌ 缺点
- 项目变大后,单个目录(比如components、screens)会爆仓,找业务相关文件要跳N个目录
- 业务逻辑分散:比如一个「帖子」功能,接口在services、状态在store、页面在screens,维护时来回切换目录,心智负担重
- 团队协作时,容易出现多人修改同一全局目录的冲突
二、现代特性式(Feature-Based)目录结构:大型项目/长期维护首选
这个是现在行业里中大型Expo项目的主流玩法,核心逻辑是按业务特性聚合代码,把一个功能的所有相关文件(接口、状态、页面、组件)都放在同一个目录下,边界清晰到离谱。
目录树示例
your-expo-app/ ├── app/ # Expo Router核心路由目录 │ ├── _layout.tsx │ ├── +not-found.tsx │ └── (tabs)/ │ ├── home.tsx │ ├── profile.tsx │ └── _layout.tsx ├── features/ # 核心:按业务特性划分目录 │ ├── auth/ # 鉴权特性(登录/注册/找回密码) │ │ ├── components/ # 鉴权专属组件(比如LoginForm、OTPInput) │ │ ├── hooks/ # 鉴权专属Hook(useLogin、useAuthStatus) │ │ ├── services/ # 鉴权专属API │ │ ├── store/ # 鉴权专属状态切片 │ │ ├── screens/ # 鉴权页面 │ │ ├── types/ # 鉴权类型定义 │ │ └── utils/ # 鉴权专属工具(比如密码加密) │ ├── posts/ # 帖子特性(列表/详情/发布) │ │ ├── components/ │ │ │ ├── PostCard.tsx │ │ │ └── PostEditor.tsx │ │ ├── hooks/ │ │ │ └── usePostList.ts │ │ ├── services/ │ │ │ └── postApi.ts │ │ ├── store/ │ │ │ └── postSlice.ts │ │ ├── screens/ │ │ │ ├── PostListScreen.tsx │ │ │ └── PostDetailScreen.tsx │ │ └── types/ │ │ └── post.ts │ └── common/ # 跨特性的通用模块(替代全局目录) │ ├── components/ # 全局通用组件(Button、Input) │ ├── hooks/ # 全局通用Hook │ ├── services/ # 全局API客户端 │ ├── store/ # 全局状态(比如主题、全局加载) │ ├── utils/ # 全局工具函数 │ └── types/ # 全局类型定义 ├── assets/ # 静态资源(和层式结构一致) │ ├── images/ │ ├── fonts/ │ └── icons/ └── package.json
为什么用这个结构?
- 业务聚合度极高,维护一个功能时,所有代码都在同一个目录下,不用来回跳
- 边界清晰,团队可以按特性分配任务,减少代码冲突
- 可扩展性拉满:新增特性时直接在features下建目录,不会影响现有代码
- 便于代码拆分:如果某个特性要独立成包,直接整个目录拎走就行
优缺点
✅ 优点
- 大型项目心智负担极低,长期维护成本小
- 团队协作友好,按特性分工,冲突少
- 可扩展性强,新增/删除特性对项目影响小
- 便于独立测试单个特性的代码
❌ 缺点
- 学习曲线比层式结构陡,新手需要先理解业务边界
- 通用模块需要提前抽离到common目录,初期可能会有重复代码(需要团队定规范)
- 小型项目用这个会显得有点“重”,目录层级偏多
三、选型建议(完全贴合你的需求)
结合你说的「长期维护、易扩展、团队协作」这几个核心目标,给你分场景推荐:
项目刚起步,团队1-3人
先用简化版层式结构快速搭建,不用一开始就搞复杂的特性划分。等项目有3-5个核心业务特性,代码量上来后,再逐步重构为特性式结构。项目已在增长,团队≥3人
直接上特性式结构!尤其是用Expo Router的话,可以把feature里的screens和app目录的路由直接对应(比如features/posts/screens/PostDetailScreen.tsx对应app/posts/[id].tsx)。
👉 重点:提前和团队约定好common目录的使用规范:什么代码能放common,什么必须留在feature里,避免common变成新的“垃圾桶”。折中方案:混合式结构
保留全局的components、hooks、services目录存放通用模块,同时用features目录管理核心业务特性的专属代码。适合既有大量通用组件,又有复杂业务特性的项目(比如电商App)。
最后给你几个团队协作小Tips
- 不管用哪种结构,一定要写目录规范文档!比如:什么是通用组件,什么是业务组件;API请求的封装规则;状态管理的命名规范。
- 用TypeScript的话,统一类型定义的存放位置,避免到处散落类型文件。
- 定期做代码评审,确保大家都遵守规范,避免代码慢慢“腐化”。
按照这个思路来,你的Expo项目不管怎么涨,都能保持清爽,团队协作也会顺畅很多~




