共计 1252 个字符,预计需要花费 4 分钟才能阅读完成。
为什么目录结构很重要
作为一名刚入门的开发者,你可能觉得把代码文件随便放一放也无所谓,反正能跑就行。但当你接手一个大型项目,或者你的小型项目逐渐膨胀时,混乱的目录结构会让你痛不欲生。我曾经就因为这个问题,花了一整天时间只为了找到一个特定的工具函数在哪里定义。

常见的新手问题包括:
- 文件散乱在项目根目录,没有分类
- 循环依赖问题(A 依赖 B,B 又依赖 A)
- 命名不一致(有的用 camelCase,有的用 snake_case)
- 过度嵌套(找到文件要点击七八层文件夹)
- 测试文件和源代码混在一起
主流目录结构方案对比
- 按功能划分 (Feature-based)
- 优点:高度内聚,功能模块自包含
- 缺点:可能导致重复代码
-
适用场景:大型复杂应用
-
按类型划分 (Type-based)
- 优点:结构清晰,易于查找
- 缺点:功能分散,修改需要跨目录
-
适用场景:小型到中型项目
-
混合模式
- 结合前两者优点,通常是顶层按类型划分,深层按功能划分
- 适用场景:大多数中等规模项目
推荐目录结构示例
my-project/
├── src/
│ ├── features/ # 功能模块
│ │ ├── auth/ # 认证相关
│ │ └── dashboard/ # 仪表板相关
│ ├── lib/ # 共享工具库
│ ├── styles/ # 全局样式
│ └── App.js # 应用入口
├── tests/ # 测试代码
├── config/ # 配置文件
└── package.json
Node.js 模块化实践示例
// src/features/auth/authService.js
export default class AuthService {// 认证相关业务逻辑}
// src/lib/httpClient.js
export function createHttpClient(config) {// 创建 HTTP 客户端}
// src/App.js
import AuthService from './features/auth/authService';
import {createHttpClient} from './lib/httpClient';
// 使用导入的模块
避坑指南
- 避免过度嵌套
-
解决方案:保持 3 - 4 层深度,过深的路径会增加认知负担
-
命名一致性
-
解决方案:团队统一命名规范,建议使用 kebab-case(短横线连接)
-
循环依赖
-
解决方案:提取公共代码到共享目录,或重新设计模块边界
-
类型定义分散
-
解决方案:集中管理类型定义,或每个模块包含自己的类型
-
测试文件位置
- 解决方案:推荐与源码同目录(如 component.js 和 component.test.js)
扩展性设计
随着项目增长,你可能需要:
- 将大型功能拆分为子功能
- 提取共享代码到独立的包
- 引入 monorepo 管理多项目
- 自动化重构工具辅助结构调整
思考与实践
- 你现在的项目结构最大的痛点是什么?
- 如果项目用户量增长 10 倍,当前结构还能胜任吗?
- 团队成员能否在 5 秒内找到特定功能的代码?
建议从重构一个小型现有项目开始实践,比如整理你的个人博客代码库。记住:好的目录结构应该像一本好书,章节分明,让读者(开发者)能够轻松找到他们需要的内容。
正文完
