NodeJS 和 ExpressJS 项目的文件夹结构
序幕
我尝试过多种后端技术,从 PHP 开始,然后转向 RoR,最后才开始接触 NodeJS。我非常喜欢 NodeJS 简化前端开发者后端开发的方式;不仅如此,NPM 生态系统还能帮助开发者轻松启动和运行复杂的项目,无需重新开发核心软件包。
这些年来,我为我的项目尝试并测试了各种文件夹结构(坦白说:我从来没有参考过网络上的任何文件夹结构,因为我想设计一些我自己的、我觉得用起来很舒服的东西,而不是预先带有偏见——这有多讽刺,因为我正在起草这个教程:))并且我终于到了一个我有足够信心分享一些适用于我的大多数 NodeJS 项目的东西的阶段。
作为本文的示例,我们将尝试构建一个应用程序,假设存在:
- 带有登陆页面的网站
- 基本身份验证
- 仪表板
- 您正在使用类似 Express 的框架
- 为前端构建工具,如 Gulp、Webpack。
- 如果您使用前端框架/库(如 React、Angular、Vue.js 等),则适用。
- 如果您希望构建仅 API 的应用程序,则适用。
对于任何应用程序来说,这都是相当标准的情况。
最后但同样重要的是,其结构或多或少类似于 Monorepo。如果您的 Node 应用仅用作 API 或网站,您可以选取其中的一些优秀部分并将其应用到您的应用中。
NodeJS 项目文件夹结构
我通常遵循的文件夹结构受到 RoR 的极大启发,因为在切换到 NodeJS 之前我一直在使用 Ruby 和 RoR。
以下是我的 NodeJS 应用的架构。我会解释一下这种文件结构背后的一些原理,并分享一些代码片段,比如如何在全局层面暴露一些配置,以及如何在应用中启动数据库连接。
/app
├── config/
│ ├── db.conf.js
│ ├── app.conf.js
│ ├── app.keys.js
│ ├── db.keys.js
│ ├── init.js
├── database/
│ ├── Redis.database.js
│ ├── Mongo.database.js
│ ├── init.js
├── routes/
│ ├── App.routes.js
│ ├── Auth.routes.js
│ ├── Dashboard.routes.js
├── utils/
│ ├── Logger.util.js
├── middleware/
│ ├── App.middleware.js
│ ├── ErrorHandler.middleware.js
│ ├── init.js
├── models/
│ ├── User.model.js
├── controllers/
│ ├── App.controller.js
│ ├── User.controller.js
├── helpers/
│ ├── App.helper.js
├── views/
│ ├── layouts/
│ ├── partials/
│ ├── support/
│ │ ├── index.ejs
│ ├── documentation/
│ │ ├── index.ejs
│ ├── index.ejs
│ ├── about.ejs
│ ├── contact.ejs
/public
├── dist/
├── images/
│ ├── dashboard/
│ ├── auth/
│ ├── documentation/
├── sitemap.xml
/samples
├── .env.sample
├── db.conf.sample
├── app.conf.sample
├── app.keys.sample
/src
├── javascript/
├── css/
/node_modules
/server.js
/package.json
/.env
项目结构简介
配置和示例
配置可分为三大类:
- 系统配置
- 应用程序配置
- 应用程序键
将配置变量存储在.env
(dotenv)中,这些变量对于配置您的应用程序(如应用程序端口、环境(生产、暂存等))是必需的。.env
配置将在您的应用程序中可用,因为它们被全局设置为 ENV 变量。
然后,您可以创建多个与应用程序相关的配置文件,例如:
- 数据库连接:数据库特定的配置,如主机、端口和名称。
- 应用程序配置:可接受的请求有效负载大小、黑名单 IP 或区域等。
- 身份验证配置:OAuth 回调 URL 等。
最后但并非最不重要的一点是,您可以创建多个文件并存储相关密钥,如 OAuth 客户端和密钥、数据库密钥、邮件密钥等。
重要提示:请勿将任何配置文件提交到 Git。请复制包含虚拟值的配置结构,并使用
/sample
文件夹下的示例文件提交到 Git。
数据库
您可以在这里创建与数据库(如 Redis、MySQL、MongoDB 等)的连接。
然后,您可以在此处获取启动连接所需的配置和密钥。这也将使您能够更轻松地在一个文件中管理与数据库连接相关的所有内容,例如在成功连接、错误连接和断开连接时添加监听器等。
稍后,可以根据需要在初始化文件下加载这些连接器。
路线
通常,您可以在此处创建一个路由文件来管理所有与应用相关的路由,但建议创建多个路由文件,这些路由文件可以分类如下:
- 网站路线
- API 路由
- 身份验证路由
- 文档路线
等等。以上方法更具可扩展性和可管理性。以下是上述方法的代码示例:
const express = require("express");
...
const websiteRoutes = require("@routes/Website.routes");
const apiRoutes = require("@routes/Api.routes");
...
app.use("/", websiteRoutes);
app.use("/api", apiRoutes);
如您所见,将路由移动到单独的文件也简化了应用程序使用这些路由的方式。
实用程序
您的应用程序可能具有多个实用功能,例如记录重要信息,或一些静态且与其他类/文件无关的功能,而不是帮助程序(本文后面定义),它可能会帮助您应用程序中的其他类或模块。
中间件
您的应用将包含多个中间件函数,这些函数可以拆分成多个,并在单个文件中启动。这些辅助函数可能包括关键中间件,例如 Body 解析器、全局错误处理程序、身份验证中间件、启用 CORS、附加自定义标头或在 ExpressJS 中设置视图引擎。
模型
每个集合(如果是 MongoDB)或每个表(如果是 MySQL)都会有一个独立的模型文件。例如:用户集合会有自己的User.model.js
文件,该文件可以进一步扩展,用于定义集合的模式结构、在数据库中设置默认值,或在将值存储到数据库之前验证用户输入。
控制器
控制器将负责处理应用程序的所有传入请求,这些请求将呈现页面作为响应,可能发送 JSON 有效负载或处理其他关键 API 相关操作,如 POST、PUT、DELETE 等。
控制器将进一步使用模型,比如在您的网站上注册时使用用户模型来创建用户,或者在请求静态页面时呈现视图文件。
助手
与实用方法不同,辅助方法本质上可以是动态的,并在需要时与特定的控制器关联。辅助方法可能包含用于解析用户发布的负载、在将其存储到数据库之前对其进行修改等方法。
视图
如果您正在开发仅 API 应用或使用单独的 SSR 库(例如 Next 或 Nuxt),则可能不需要此文件夹。当您使用 Express View Engine(例如 Pug 或 EJS)时,这可能会很有用。
您可以进一步将视图划分为布局、页面和部分视图。布局可以在相似的页面之间共享,并且一个网站可以有多个布局。最后,部分视图将包含网页所需的通用组件,例如页眉、页脚、侧边栏等。
民众
顾名思义,此文件夹下的所有内容都将对您的网站用户公开访问。CSS、JavaScript 和图像都属于此文件夹。
您的应用程序可能会使用 Webpack 和 Gulp 等工具,它们将编译(最小化、预处理)您的 (S)CSS 和 JS 文件并移动到公共文件夹下,稍后将在网页上链接。
您还可以在该dist/
文件夹下构建和输出您的 React(或类似的 lib/framework)应用程序。
源码
由于App
文件夹负责处理所有后端逻辑,Src
如果您使用 SASS、ES 6 / Next,文件夹将保存您的 JavaScript 和 CSS 文件,这些文件需要经过转译、编译、最小化和丑化才能提供给最终用户。
Src
文件夹将进一步保存像CSS
和这样的目录JavaScript
,可以根据您的需要进行定制。
init.js
在结束本文之前,我对文件进行了简单的解释,init.js
文件将需要其余文件并将它们导出到应用程序的其他文件中,这样,如果您希望使用所有文件,则不必每次都需要多个文件。
结论
我在 Node 上构建的所有项目中,或多或少都遵循了上述文件夹结构。它对我来说很有效,如果它能帮到你,我很乐意听取你的意见。
最后,您应该尝试根据您的需要修改文件夹结构,以便长期管理和扩展它。
有用的资源
最后,我很乐意分享一些我用来管理配置的包,简化在各个嵌套级别上需要文件的过程,以及一些 Linting 包,以在很大程度上标准化您的代码。
文章来源:https://dev.to/mr_ali3n/folder-struct-for-nodejs-expressjs-project-435l