Nodejs: Good Practices to Structure an Express App

Nodejs: Good Practices to Structure an Express App

这是我总结的几个不错的 Express 应用开发实践,最近在很努力地学英语,所以尝试用英文写啦。 http://zihua.li/2014/05/good-practices-to-structure-an-express-app/

语法、表述错误啥的求 Pull Request~: https://github.com/luin/blog/blob/master/content/tech/2014-05-21_good-practices-to-structure-an-express-app.md


2 回复

Node.js: Good Practices to Structure an Express App

Building a scalable and maintainable application in Node.js with Express requires following some best practices. Below, I will outline several good practices that can help you structure your Express application effectively.

1. Project Structure

A well-organized project structure is crucial for maintaining a clean codebase. Here’s an example of a typical directory structure:

myapp/
├── app.js
├── config/
│   └── db.js
├── controllers/
│   └── userController.js
├── models/
│   └── userModel.js
├── routes/
│   └── userRoutes.js
├── utils/
│   └── logger.js
└── views/
    └── index.ejs
  • app.js: The main entry point of the application.
  • config/: Configuration files, such as database settings.
  • controllers/: Business logic and controller functions.
  • models/: Data models and database interactions.
  • routes/: Routes and route handlers.
  • utils/: Utility functions.
  • views/: View templates.

2. Use Environment Variables

Environment variables are essential for managing configuration across different environments (development, testing, production). You can use the dotenv package to load environment variables from a .env file.

// .env
DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

// app.js
require('dotenv').config();
const mongoose = require('mongoose');
mongoose.connect(`mongodb://${process.env.DB_HOST}/${process.env.DB_NAME}`, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

3. Middleware Management

Middleware functions are the backbone of Express applications. It’s important to manage them efficiently by organizing them into reusable and modular components.

// middleware/logger.js
function logger(req, res, next) {
  console.log(`${req.method} ${req.url}`);
  next();
}

module.exports = logger;

// app.js
const logger = require('./middleware/logger');
app.use(logger);

4. Error Handling

Error handling should be done in a centralized manner to ensure consistency and maintainability.

// app.js
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

// Or in a separate error handler file
// errorHandlers.js
module.exports = (err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
};

// app.js
const errorHandler = require('./errorHandlers');
app.use(errorHandler);

5. API Versioning

API versioning is crucial for maintaining backward compatibility and managing changes over time.

// app.js
app.use('/api/v1', require('./routes/v1/userRoutes'));
app.use('/api/v2', require('./routes/v2/userRoutes'));

By following these best practices, you can create a robust and maintainable Express application. Each practice helps in keeping the codebase organized, scalable, and easy to understand.


好的,下面是一个关于如何使用良好的实践来结构化一个Express应用的回答。这个回答将涵盖一些关键点,并附带示例代码。

1. 目录结构

良好的目录结构可以帮助你更好地管理代码,使其更易于维护和扩展。以下是一个常见的目录结构:

my-express-app/
├── app.js
├── config/
│   └── db.js
├── controllers/
│   └── userController.js
├── routes/
│   └── userRoutes.js
├── models/
│   └── userModel.js
├── middlewares/
│   └── authMiddleware.js
├── utils/
│   └── helperFunctions.js
└── package.json

2. 配置文件

将配置文件分离出来可以让你轻松切换不同的环境(如开发环境、测试环境和生产环境)。

// config/db.js
const mongoose = require('mongoose');
const config = require('../config/config');

module.exports = () => {
    mongoose.connect(config.db.uri, { useNewUrlParser: true, useUnifiedTopology: true });
};

3. 路由分离

将路由分离到不同的文件中可以使你的应用更容易理解和维护。

// routes/userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');

router.get('/', userController.getAllUsers);
router.post('/', userController.createUser);

module.exports = router;

4. 控制器分离

控制器负责处理业务逻辑,分离控制器可以使你的代码更加清晰。

// controllers/userController.js
const User = require('../models/userModel');

exports.getAllUsers = async (req, res) => {
    try {
        const users = await User.find();
        res.status(200).json(users);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
};

exports.createUser = async (req, res) => {
    try {
        const newUser = new User(req.body);
        await newUser.save();
        res.status(201).json(newUser);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
};

5. 中间件

中间件用于处理请求和响应。你可以创建自定义中间件来处理身份验证、日志记录等。

// middlewares/authMiddleware.js
const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
    const token = req.header('Authorization').split(' ')[1];
    if (!token) {
        return res.status(401).json({ message: 'Access denied' });
    }
    try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        req.user = decoded;
        next();
    } catch (error) {
        res.status(400).json({ message: 'Invalid token' });
    }
};

6. 错误处理

良好的错误处理机制可以确保你的应用在遇到错误时能够优雅地响应。

// app.js
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send({ message: err.message });
});

以上是一些良好的实践,帮助你更好地结构化一个Express应用。希望这些示例对你有所帮助!

回到顶部