」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 如何在 Node.js (Express.js) 中建立後端程式碼

如何在 Node.js (Express.js) 中建立後端程式碼

發佈於2024-08-25
瀏覽:803

How to Structure Your Backend Code in 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

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

const express = require('express');
const app = express();
const config = require('./config');
const routes = require('./routes');
// Middleware setup
app.use(express.json());
// Routes setup
app.use('/api', routes);
// Start server
const PORT = config.port || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
module.exports = app;

垃圾桶
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 === 'string' ? 'Pipe '   port : 'Port '   port;
  switch (error.code) {
    case 'EACCES':
      console.error(bind   ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind   ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}
function onListening() {
  const addr = server.address();
  const bind = typeof addr === 'string' ? 'pipe '   addr : 'port '   addr.port;
  debug('Listening on '   bind);
}

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

示例:config/index.js

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

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

示例: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({ message: err.message });
  }
};

中间件
中间件功能用于在请求到达控制器之前对其进行处理。它们可以处理身份验证、日志记录和请求验证等任务。

示例:middleware/auth.js

module.exports = (req, res, next) => {
  const token = req.header('Authorization');
  if (!token) return res.status(401).json({ message: 'Access Denied' });
  try {
    const verified = jwt.verify(token, process.env.JWT_SECRET);
    req.user = verified;
    next();
  } catch (err) {
    res.status(400).json({ message: 'Invalid Token' });
  }
};

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

示例:models/customer.js

const mongoose = require('mongoose');
const customerSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});
module.exports = mongoose.model('Customer', customerSchema);

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

示例:routes/api.js

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

民众
公共目录包含直接向客户端提供服务的静态文件,例如 CSS、JavaScript 和图像。

示例:目录结构

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

观看次数
视图是为客户端呈现 HTML 的模板。使用 EJS、Pug 或 Handlebars 等模板引擎,您可以生成动态 HTML。

示例:views/index.ejs



  My App

Welcome to My App

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

示例:目录结构

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

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

示例:utils/validation.js

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

节点模块
node_modules 目录包含您的项目所需的所有依赖项。该目录由 npm(或yarn)管理,包含从 npm 注册表安装的包。

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

版本聲明 本文轉載於:https://dev.to/kafeel_ahmad/how-to-structure-your-backend-code-in-nodejs-expressjs-2e07?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 文件的力量:閱讀如何改變我在 JamSphere 上使用 Redux 的體驗
    文件的力量:閱讀如何改變我在 JamSphere 上使用 Redux 的體驗
    作為開發人員,我們經常發現自己一頭扎進新的庫或框架,渴望將我們的想法變為現實。跳過文件並直接跳到編碼的誘惑很強烈——畢竟,這有多難呢?但正如我透過建立音樂管理平台 JamSphere 的經驗所了解到的那樣,跳過這一關鍵步驟可能會將順利的旅程變成充滿挑戰的艱苦戰鬥。 跳過文檔的魅力 ...
    程式設計 發佈於2024-11-07
  • 如何在PHP多子網域應用中精準控制Cookie域?
    如何在PHP多子網域應用中精準控制Cookie域?
    在PHP 中控制Cookie 域和子域在PHP 中控制Cookie 域和子域建立多子網域網站時,必須控制會話cookie 的網域確保每個子網域的正確會話管理。然而,手動設定網域時,PHP 的 cookie 處理似乎存在差異。 header("Set-Cookie: cookiename=c...
    程式設計 發佈於2024-11-07
  • 如何取得已安裝的 Go 軟體包的完整清單?
    如何取得已安裝的 Go 軟體包的完整清單?
    檢索Go 中已安裝軟體包的綜合清單在多台電腦上傳輸Go 軟體包安裝時,有必要取得詳細的清單所有已安裝的軟體包。本文概述了此任務的簡單且最新的解決方案。 解決方案:利用“go list”與過時的答案相反,當前的建議列出Go 中已安裝的軟體包是使用“go list”命令。透過指定三個文字句點 ('...
    程式設計 發佈於2024-11-07
  • Java中的三元運算子可以不回傳值嗎?
    Java中的三元運算子可以不回傳值嗎?
    三元運算子:深入研究程式碼最佳化三元運算子:深入研究程式碼最佳化雖然三元運算子(?:) 是Java 中的一個強大工具,但它了解其限制至關重要。一個常見的誤解是可以在不傳回值的情況下使用它。 與這種看法相反,Java 不允許在沒有 return 語句的情況下進行三元運算。三元運算子的目的是評估條件並將...
    程式設計 發佈於2024-11-07
  • 為什麼您應該在下一個 PHP 專案中嘗試 Lithe?
    為什麼您應該在下一個 PHP 專案中嘗試 Lithe?
    Lithe 是尋求簡單性與強大功能之間平衡的開發人員的完美 PHP 框架。如果您厭倦了使開發緩慢且令人困惑的繁瑣框架,Lithe 提供了一種極簡但極其靈活的方法,旨在使您的工作更快、更有效率。 1. 輕量且超快 Lithe 的開發重點是輕量級,允許您以很少的開銷創建應用程式。與其他...
    程式設計 發佈於2024-11-07
  • 如何處理 Android 中的網路連線變更?
    如何處理 Android 中的網路連線變更?
    處理Android 中的互聯網連接變化問題集中在需要一個可以監視互聯網連接變化的廣播接收器,因為現有代碼僅檢測連接變化。 為了解決這個問題,這裡有一個替代方法:public class NetworkUtil { public static final int TYPE_WIFI = 1; ...
    程式設計 發佈於2024-11-07
  • Python 3.x 的 Super() 在沒有參數的情況下如何運作?
    Python 3.x 的 Super() 在沒有參數的情況下如何運作?
    Python 3.x 的超級魔法:解開謎團Python 3.x 在其super() 方法中引入了令人驚訝的轉折,允許無參數呼叫。這種看似無害的改變在幕後卻帶來了重大的後果和內在的魔力。 揭開魔力為了維護 DRY 原則,新的 super() 行為繞過了顯式類別命名。它有一個特殊的 class 單元,用...
    程式設計 發佈於2024-11-07
  • Tailwind Flex:Flexbox 實用程式初學者指南
    Tailwind Flex:Flexbox 實用程式初學者指南
    Tailwind Flex 提供了一种创建响应式布局的有效方法,无需编写复杂的 CSS。通过使用 flex、flex-row 和 flex-col 等简单的实用程序,您可以轻松对齐和排列元素。 Tailwind Flex 非常适合希望简化布局创建同时保持对对齐、方向和间距的完全控制的开发人员 - 所...
    程式設計 發佈於2024-11-07
  • ETL:從文字中提取人名
    ETL:從文字中提取人名
    假設我們想要抓取chicagomusiccompass.com。 如你所見,它有幾張卡片,每張卡片代表一個事件。現在,讓我們來看看下一篇: 注意事件名稱是: jazmin bean: the traumatic livelihood tour 所以現在的問題是:我們要如何從文本中提取藝術家的名字?...
    程式設計 發佈於2024-11-07
  • 如何控制 C++ ostream 輸出中的浮點精度?
    如何控制 C++ ostream 輸出中的浮點精度?
    在Ostream 輸出中維護浮點精度在Ostream 輸出中維護浮點精度在C 中,在ostream 運算中使用“
    程式設計 發佈於2024-11-07
  • 如何保證PHP會話的安全銷毀?
    如何保證PHP會話的安全銷毀?
    確保銷毀 PHP 會話儘管資訊存在衝突,但仍有有效的方法可以安全地消除 PHP 會話。要實現此最終終止,遵循多步驟流程至關重要。 會話終止的基本步驟刪除會話資料:啟動會話後與session_start() 一起,使用unset() 刪除與特定會話變數關聯的任何儲存數據,例如$_SESSION[...
    程式設計 發佈於2024-11-07
  • 為什麼我的 MongoDB 文件在 Go 中使用 TTL 索引 5 秒後沒有過期?
    為什麼我的 MongoDB 文件在 Go 中使用 TTL 索引 5 秒後沒有過期?
    在Go 中使用MongoDB 在指定的秒數後使文件過期使用TTL 索引,MongoDB 允許您在指定的秒數後自動使文件過期期間。本文示範如何使用官方 mongo-go-driver 在 Go 中實現此目的。 按照MongoDB 文檔,程式碼顯示如何:建立帶有expireAfterSeconds 的索...
    程式設計 發佈於2024-11-07
  • 使用 JetForms 簡化表單管理:完整指南
    使用 JetForms 簡化表單管理:完整指南
    在當今的數位環境中,管理表單提交很快就會變得不堪重負,特別是當您跨不同平台處理多個表單時。無論是網站上的簡單聯絡表單還是產品的全面調查,手動維護表單提交都是一件麻煩事。這就是 JetForms 的用武之地——一個簡化流程、節省您時間和精力的精簡平台。 在本指南中,我將引導您了解如何開始使用 Jet...
    程式設計 發佈於2024-11-07
  • 使用清單清單時如何修復 Tensorflow 中的「不支援的物件類型浮點」錯誤?
    使用清單清單時如何修復 Tensorflow 中的「不支援的物件類型浮點」錯誤?
    Tensorflow - ValueError:無法將NumPy 數組轉換為張量(不支援的物件類型float)背景您正在嘗試訓練一個)背景]您正在嘗試訓練一個包含清單清單的模型,每個清單包含1000 個浮點數,但遇到錯誤「無法將NumPy 陣列轉換為張量(不支援的物件類型浮點)。」x_train =...
    程式設計 發佈於2024-11-07
  • 如何使用 contains() 函數在 XPath 中實作不區分大小寫的搜尋?
    如何使用 contains() 函數在 XPath 中實作不區分大小寫的搜尋?
    不區分大小寫的 XPath contains() 函數在 XPath 中,contains() 函數區分大小寫。但是,有一些方法可以解決此限制。 方法1:翻譯字元此方法涉及在檢查子字串之前將字元轉換為小寫或大寫:/html/body//text()[ contains( translat...
    程式設計 發佈於2024-11-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3