如何在 Node.js(Express.js)中构建后端代码结构

在使用 Express.js 开发 Node.js 应用程序时,有效地构建代码库结构对于可维护性、可扩展性和协作便利性至关重要。一个组织良好的项目结构能够帮助您管理复杂性,使代码更易于导航和理解。在这篇博客中,我们将探讨 Express.js 应用程序的典型文件夹结构,并解释每个目录和文件的用途。

项目结构概览

以下是一个 Express.js 应用程序常见的文件夹结构:

📁
├── 📄 app.js
├── 📁 bin
├── 📁 config
├── 📁 controllers
│   ├── 📄 customer.js
│   ├── 📄 product.js
│   └──...
├── 📁 middleware
│   ├── 📄 auth.js
│   ├── 📄 logger.js
│   └──...
├── 📁 models
│   ├── 📄 customer.js
│   ├── 📄 product.js
│   └──...
├── 📁 routes
│   ├── 📄 api.js
│   ├── 📄 auth.js
│   └──...
├── 📁 public
│   ├── 📁 css
│   ├── 📁 js
│   ├── 📁 images
│   └──...
├── 📁 views
│   ├── 📄 index.ejs
│   ├── 📄 product.ejs
│   └──...
├── 📁 tests
│   ├── 📁 unit
│   ├── 📁 integration
│   ├── 📁 e2e
│   └──...
├── 📁 utils
│   ├── 📄 validation.js
│   ├── 📄 helpers.js
│   └──...
└── 📁 node_modules

每个目录和文件的解释

app.js

app.js文件是您应用程序的入口点。在这里,您初始化 Express 应用程序,设置中间件,定义路由,并启动服务器。可以将其视为您的 Web 应用程序的控制中心。

const express = require('express');
const app = express();
const config = require('./config');
const routes = require('./routes');
​
// 中间件设置
app.use(express.json());
​
// 路由设置
app.use('/api', routes);
​
// 启动服务器
const PORT = config.port || 3000;
app.listen(PORT, () => {
  console.log(`服务器在端口 ${PORT} 上运行`);
});
​
module.exports = app;
bin

bin目录通常包含用于启动 Web 服务器的脚本。这些脚本可用于设置环境变量或管理不同的环境(例如,开发、生产)。

示例:bin/www

#!/usr/bin/env node
​
const app = require('../app');
const debug = require('debug')('your-app:server');
const http = require('http');
​
const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
​
const server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
​
function normalizePort(val) {
  const port = parseInt(val, 10);
  if (isNaN(port)) return val;
  if (port >= 0) return port;
  return false;
}
​
function onError(error) {
  if (error.syscall!== 'listen') throw error;
  const bind = typeof port === 'tring'? 'Pipe ' port : 'Port ' port;
  switch (error.code) {
    case 'EACCES':
      console.error(bind + '要提升权限');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + '被占用');
      process.exit(1);
      break;
    default:
      throw error;
  }
}
​
function onListening() {
  const addr = server.address();
  const bind = typeof addr === 'tring'? 'pipe ' addr : 'port ' addr.port;
  debug('在 ' bind + '监听');
}
config

config目录包含您应用程序的配置文件,例如数据库连接、服务器设置和环境变量。

示例:config/index.js

module.exports = {
  port: process.env.PORT || 3000,
  db: {
    host: 'localhost',
    port: 27017,
    name: 'ydatabase'
  }
};
controllers

控制器包含处理传入请求并生成响应的逻辑。controllers目录中的每个文件通常对应于应用程序的不同部分(例如,客户、产品)。

示例:controllers/customer.js

const Customer = require('../models/customer');
​
exports.getAllCustomers = async (req, res) => {
  try {
    const customers = await Customer.find();
    res.json(customers);
  } catch (err) {
    res.status(500).json({ 消息: err.message });
  }
};
middleware

中间件函数用于在请求到达控制器之前处理请求。它们可以处理诸如身份验证、日志记录和请求验证等任务。

示例:middleware/auth.js

module.exports = (req, res, next) => {
  const token = req.header('Authorization');
  if (!token) return res.status(401).json({ 消息: '访问被拒绝' });
​
  try {
    const verified = jwt.verify(token, process.env.JWT_SECRET);
    req.user = verified;
    next();
  } catch (err) {
    res.status(400).json({ 消息: '无效令牌' });
  }
};
models

模型定义了您数据的结构并处理与数据库的交互。每个模型文件通常对应于不同的数据实体(例如,客户、产品)。

示例:models/customer.js

const mongoose = require('mongoose');
​
const customerSchema = new mongoose.Schema({
  名称: {
    类型: String,
    必需: true
  },
  电子邮件: {
    类型: String,
    必需: true,
    唯一: true
  },
  创建时间: {
    类型: Date,
    默认: Date.now
  }
});
​
module.exports = mongoose.model('Customer', customerSchema);
routes

路由定义了应用程序不同部分的路径,并将它们映射到相应的控制器。

示例:routes/api.js

const express = require('express');
const router = express.Router();
const customerController = require('../controllers/customer');
​
router.get('/customers', customerController.getAllCustomers);
​
module.exports = router;
public

public目录包含直接提供给客户端的静态文件,如 CSS、JavaScript 和图像。

示例:目录结构

public/
├── css/
├── js/
├── images/
views

视图是为客户端呈现 HTML 的模板。使用像 EJS、Pug 或 Handlebars 这样的模板引擎,您可以生成动态 HTML。

示例:views/index.ejs

<!DOCTYPE html>
<html>
<head>
  <title>我的应用程序</title>
  <link rel="stylesheet" href="/css/styles.css">
</head>
<body>
  <h1>欢迎来到我的应用程序</h1>
  <div id="content">
    <%- content %>
  </div>
</body>
</html>
tests

tests目录包含用于确保您的应用程序正常工作的测试文件。测试通常分为单元测试、集成测试和端到端(e2e)测试。

示例:目录结构

tests/
├── unit/
├── integration/
├── e2e/
utils

实用函数和辅助模块存储在utils目录中。这些函数执行整个应用程序中使用的常见任务,如验证和格式化。

示例:utils/validation.js

exports.isEmailValid = (email) => {
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return re.test(String(email).toLowerCase());
};
node_modules

node_modules目录包含项目所需的所有依赖项。此目录由 npm(或 yarn)管理,并包括从 npm 注册表安装的包。

结论

使用 Express.js 构建结构良好的 Node.js 应用程序可增强可维护性、可扩展性和协作性。结构中的每个目录和文件都有特定的用途,从处理配置和定义路由到管理中间件和呈现视图。通过有效地组织代码库,您可以轻松构建强大且可扩展的应用程序。

请注意,在尝试获取相关网页内容时,出现了网页解析失败或加载超时的问题,请您检查网页或稍后重试。

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幻想多巴胺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值