使用 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');

// 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

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目錄保存應用程式的設定文件,例如資料庫連線、伺服器設定和環境變數。

範例: config/index.js

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

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

middleware

中間件功能用於在請求到達控制器之前對其進行處理。它們可以處理身份驗證、日誌記錄和請求驗證等任務。

範例: 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

模型定義資料的結構並處理與資料庫的交互作用。每個模型檔案通常對應於不同的資料實體(例如,客戶、產品)。

範例: 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

路由定義了應用程式不同部分的路徑,並將它們對應到適當的控制器。

範例: 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>My App</title>
  <link rel="stylesheet" href="/css/styles.css">
</head>
<body>
  <h1>Welcome to My App</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 應用程式可以增強可維護性、可擴展性和協作性。結構中的每個目錄和檔案都有特定的用途,從處理配置和定義路由到管理中間件和渲染視圖。透過有效地組織程式碼庫,您可以輕鬆建立強大且可擴展的應用程式。


原文出處:https://dev.to/vyan/how-to-structure-your-backend-code-in-nodejs-expressjs-2bdd


共有 0 則留言