对于一个已经拥有了node项目初始化经验,以及掌握了node与npm的基本命令的你,了解以下node项目的目录结构设计很有必要。
阅读前嘱托一句,建议参考本文的目录结构设计思想,不要照搬照抄,设计一个受自己掌控、符合自己习惯的目录结构才是最优解。
参考官方文档说明https://node.org.cn/docs/latest/api/packages.html#subpath-imports
优先处理文件路径标识符问题,主要为了方便在设计目录结构时,可以在互相引用时,不用存在使用绝对路径/相对路径的烦恼
// package.json{"imports":{"#root/*":"./*","#src/*":"./src/*"},}回答为什么使用#而非是@的原因,首先官方强制要求要使用#,目的是为了与外部包区分开
所以在nodejs后端项目内使用#,在前端项目(webpack/vite/gulp)中使用@,要记住区分
下面是我初步形成的目录结构,供大家参考:
node-js-koa/├── package.json // npm 项目描述文件,定义依赖、脚本和项目元数据├── README.md // 中文项目说明文档├── README.en.md // 英文项目说明文档(本文档)├── LICENSE // 开源许可证├── .gitignore // Git 忽略规则配置├── .env.development // 开发环境环境变量配置├── .env.preview // 预览环境环境变量配置├── .env.production // 生产环境环境变量配置├── main.js // 应用主入口,负责启动热更新 watcher 加载环境变量、初始化数据库、注册中间件和路由、启动 HTTP 服务├── db_sqlite/ // SQLite 数据库目录│ ├── database.sqlite // SQLite 数据库文件│ ├── init-db.js // 数据库初始化脚本│ └── backups/ // 数据库备份目录│ ├── database/ // 数据库文件备份│ ├── sql/ // SQL 初始化脚本备份│ ├── README.md // 备份说明文档│ └── backup-db.sh // 数据库备份 Shell 脚本├── docs/ // 项目文档目录│ └── apifox/ // Apifox 接口文档│ └── postman/ // postman 接口文档├── plugin/ // 插件目录│ ├── hot-reload/ // 热更新插件│ │ ├── index.js // 热更新核心逻辑,文件监听、进程管理│ │ ├── client.js // 热更新客户端脚本,注入浏览器实现自动刷新│ │ ├── hot-reload-middleware.js // 热更新 Koa 中间件,提供客户端脚本和版本号接口│ │ ├── version.js // 热更新版本号管理│ │ ├── process-on-event.js // 进程事件处理│ │ └── readme.md // 热更新插件说明│ └── llm-sdk/ // LLM SDK 插件目录│ ├── openai/ // OpenAI API 封装│ ├── deepseek/ // DeepSeek API 封装│ └── anthropic/ // Anthropic API 封装├── public/ // 静态资源目录,直接对外提供文件访问│ ├── index.html // 前端应用入口页面│ ├── assets/ // 静态资源文件(CSS、JS、图片等)│ └── database/ // 数据库工具页面│ ├── sql-tool.html // SQL 在线执行工具页面│ └── readme.md // 数据库工具说明├── src/ // 核心业务代码目录│ ├── config/ // 配置文件目录│ │ ├── database.config.js // 数据库连接配置│ │ ├── jwt.config.js // JWT 认证配置│ │ ├── logger.config.js // 日志配置│ │ ├── permissions.config.js // 权限配置数据,用于 /userInfo 接口返回前端权限参考数据│ │ ├── routes.config.js // 路由配置数据,用于 /userInfo 接口返回前端菜单路由参考数据│ │ └── redis.config.js // Redis 连接配置│ ├── constants/ // 常量定义目录│ │ └── code.js // 业务状态码常量│ ├── routes/ // 路由定义目录,只做路径映射│ │ ├── index.js // 路由统一入口,聚合所有模块路由│ │ ├── login.route.js // 登录认证路由│ │ ├── user.route.js // 用户管理路由│ │ ├── role.route.js // 角色管理路由│ │ ├── menu.route.js // 菜单管理路由│ │ ├── dept.route.js // 部门管理路由│ │ ├── post.route.js // 岗位管理路由│ │ ├── dict.route.js // 字典类型路由│ │ ├── dict-data.route.js // 字典数据路由│ │ ├── notice.route.js // 通知公告路由│ │ ├── sql.route.js // SQL 执行路由│ │ ├── version.route.js // 版本信息路由│ │ ├── example.route.js // 示例路由│ │ └── llm-route.js // LLM 大模型路由│ ├── controllers/ // 控制器目录,面向 HTTP 请求与响应│ │ ├── login.controller.js // 登录认证控制器│ │ ├── user.controller.js // 用户管理控制器│ │ ├── role.controller.js // 角色管理控制器│ │ ├── menu.controller.js // 菜单管理控制器│ │ ├── dept.controller.js // 部门管理控制器│ │ ├── post.controller.js // 岗位管理控制器│ │ ├── dict.controller.js // 字典类型控制器│ │ ├── dict-data.controller.js // 字典数据控制器│ │ ├── notice.controller.js // 通知公告控制器│ │ ├── sql.controller.js // SQL 执行控制器│ │ ├── version.controller.js // 版本信息控制器│ │ └── example.controller.js // 示例控制器│ ├── services/ // 业务逻辑层目录,承载核心业务规则│ │ ├── login.service.js // 登录认证业务逻辑│ │ ├── user.service.js // 用户管理业务逻辑│ │ ├── role.service.js // 角色管理业务逻辑│ │ ├── menu.service.js // 菜单管理业务逻辑│ │ ├── dept.service.js // 部门管理业务逻辑│ │ ├── post.service.js // 岗位管理业务逻辑│ │ ├── dict.service.js // 字典类型业务逻辑│ │ ├── dict-data.service.js // 字典数据业务逻辑│ │ ├── notice.service.js // 通知公告业务逻辑│ │ ├── sql.service.js // SQL 执行业务逻辑│ │ ├── version.service.js // 版本信息业务逻辑│ │ └── example.service.js // 示例业务逻辑│ ├── dao/ // 数据访问对象目录,面向数据读写│ │ ├── base.dao.js // 基础 DAO 封装,提供通用 CRUD 方法│ │ ├── login.dao.js // 登录认证数据访问│ │ ├── user.dao.js // 用户管理数据访问│ │ ├── role.dao.js // 角色管理数据访问│ │ ├── menu.dao.js // 菜单管理数据访问│ │ ├── dept.dao.js // 部门管理数据访问│ │ ├── post.dao.js // 岗位管理数据访问│ │ ├── dict.dao.js // 字典类型数据访问│ │ ├── dict-data.dao.js // 字典数据数据访问│ │ ├── notice.dao.js // 通知公告数据访问│ │ ├── sql.dao.js // SQL 执行数据访问│ │ ├── version.dao.js // 版本信息数据访问│ │ └── example.dao.js // 示例数据访问│ ├── middlewares/ // 中间件目录,处理通用横切逻辑│ │ ├── auth.js // JWT 认证中间件│ │ ├── cors.js // 跨域处理中间件│ │ ├── error.js // 全局异常处理中间件│ │ ├── logger.js // 请求日志中间件│ │ ├── koa.start.js // Koa 启动信息中间件│ │ ├── process-events.js // 进程事件监听中间件│ │ ├── redirectDefaultHtml.js // 默认页面重定向中间件│ │ ├── snake_case-to-cameCase.js // 请求/响应字段命名转换中间件(snake_case 转 camelCase)│ │ ├── static-service.js // 静态文件服务中间件│ │ └── readme.md // 中间件说明文档│ ├── validators/ // 请求参数校验目录│ │ └── login.js // 登录请求参数校验│ └── utils/ // 工具函数目录,保持纯粹不依赖业务上下文│ ├── browser.js // 浏览器操作工具(自动打开、检测已有标签页刷新)│ ├── captcha.js // 验证码生成工具│ ├── sm4.js // SM4 国密算法工具│ ├── file-url.js // 文件 URL 处理工具│ └── utils.js // 通用工具函数集合└── test/ // 测试目录
推荐的请求处理链路:
Request -> routes -> middlewares -> controllers -> services -> dao -> sqlite -> Response各核心层设计原则:
routes (API路由)只做路径映射,不写复杂业务逻辑。middlewares (中间件)处理通用横切逻辑,不绑定具体业务流程。controllers (控制器)面向 HTTP 请求与响应,不直接承载复杂业务规则。services (业务服务)面向业务用例,是后端项目的主要业务承载层。dao (sql语句编写,数据库操作)面向数据读写,避免数据访问细节泄漏到控制层。utils (公用函数)保持纯粹,不依赖具体业务上下文。config (项目关键配置)独立支撑项目的关键配置,如:db、log、redis等constants (项目固定常量) 只对项目公用的常量进行统一管理,如:code、msg等validators (项目公用校验) 单独处理项目内的公用校验函数,一切需要校验的参数形式都在此目录进行管理可以使用下方命令,在项目根目录执行,快速创建结构:
mkdir -p db_sqlite/backups/databasemkdir -p db_sqlite/backups/sqlmkdir -p docs/apifoxmkdir -p docs/postmanmkdir -p plugin/hot-reloadmkdir -p plugin/llm-sdk/openaimkdir -p plugin/llm-sdk/deepseekmkdir -p plugin/llm-sdk/anthropicmkdir -p public/assetsmkdir -p public/databasemkdir -p src/configmkdir -p src/constantsmkdir -p src/routesmkdir -p src/controllersmkdir -p src/servicesmkdir -p src/daomkdir -p src/middlewaresmkdir -p src/validatorsmkdir -p src/utilsmkdir -p testtouch package.jsontouch README.mdtouch README.en.mdtouch LICENSEtouch .gitignoretouch .env.developmenttouch .env.previewtouch .env.productiontouch main.jstouch db_sqlite/init-db.jstouch db_sqlite/backups/README.mdtouch db_sqlite/backups/backup-db.shtouch plugin/hot-reload/index.jstouch plugin/hot-reload/client.jstouch plugin/hot-reload/hot-reload-middleware.jstouch plugin/hot-reload/version.jstouch plugin/hot-reload/process-on-event.jstouch plugin/hot-reload/readme.mdtouch public/index.htmltouch public/database/sql-tool.htmltouch public/database/readme.mdtouch src/config/database.config.jstouch src/config/jwt.config.jstouch src/config/logger.config.jstouch src/config/permissions.config.jstouch src/config/routes.config.jstouch src/config/redis.config.jstouch src/constants/code.jstouch src/routes/index.jstouch src/routes/login.route.jstouch src/routes/user.route.jstouch src/routes/role.route.jstouch src/routes/menu.route.jstouch src/routes/dept.route.jstouch src/routes/post.route.jstouch src/routes/dict.route.jstouch src/routes/dict-data.route.jstouch src/routes/notice.route.jstouch src/routes/sql.route.jstouch src/routes/version.route.jstouch src/routes/example.route.jstouch src/routes/llm-route.jstouch src/controllers/login.controller.jstouch src/controllers/user.controller.jstouch src/controllers/role.controller.jstouch src/controllers/menu.controller.jstouch src/controllers/dept.controller.jstouch src/controllers/post.controller.jstouch src/controllers/dict.controller.jstouch src/controllers/dict-data.controller.jstouch src/controllers/notice.controller.jstouch src/controllers/sql.controller.jstouch src/controllers/version.controller.jstouch src/controllers/example.controller.jstouch src/services/login.service.jstouch src/services/user.service.jstouch src/services/role.service.jstouch src/services/menu.service.jstouch src/services/dept.service.jstouch src/services/post.service.jstouch src/services/dict.service.jstouch src/services/dict-data.service.jstouch src/services/notice.service.jstouch src/services/sql.service.jstouch src/services/version.service.jstouch src/services/example.service.jstouch src/dao/base.dao.jstouch src/dao/login.dao.jstouch src/dao/user.dao.jstouch src/dao/role.dao.jstouch src/dao/menu.dao.jstouch src/dao/dept.dao.jstouch src/dao/post.dao.jstouch src/dao/dict.dao.jstouch src/dao/dict-data.dao.jstouch src/dao/notice.dao.jstouch src/dao/sql.dao.jstouch src/dao/version.dao.jstouch src/dao/example.dao.jstouch src/middlewares/auth.jstouch src/middlewares/cors.jstouch src/middlewares/error.jstouch src/middlewares/logger.jstouch src/middlewares/koa.start.jstouch src/middlewares/process-events.jstouch src/middlewares/redirectDefaultHtml.jstouch src/middlewares/snake_case-to-cameCase.jstouch src/middlewares/static-service.jstouch src/middlewares/readme.mdtouch src/validators/login.jstouch src/utils/browser.jstouch src/utils/captcha.jstouch src/utils/sm4.jstouch src/utils/file-url.jstouch src/utils/utils.js由于我也是刚刚开始学习nodejs,所以兄弟们不要完全照搬,即拿即用不是我发布这篇文章的目的,我始终认为思想才是一切的源头,我对此项目的目录结构设计思想才是我要表达给大家参考的
就如同我在往期文章中,比较有代表性的vue组件封装思想、react组件封装思想,都是为了向大家展示我的封装思想、设计思想
最后,谢谢大家的耐心阅读