全书目录

第十二篇:Express 完全指南 —— 老城区主干道宇宙

第十三章:模块拆分 —— 别把整座城都画在一张纸上

1 分钟 265 字 第 251 / 962 个阅读单元

Express 本身很轻,所以越到真实项目,越需要你主动分层。

一个适合初学者的拆法:

text
src
├── app.js
├── server.js
├── routes
│   ├── roadRoutes.js
│   └── districtRoutes.js
├── controllers
│   └── roadController.js
├── services
│   └── roadService.js
├── middlewares
│   ├── logger.js
│   ├── notFound.js
│   └── errorHandler.js
├── public
└── views
#1. 每层职责
text
routes       = 地图,只管“哪个路口去哪个窗口”
controllers  = 窗口,只管“接请求、调服务、回响应”
services     = 办事员,只管“业务逻辑、数据处理”
middlewares  = 检查站、统一拦截器
public       = 公告栏资源
views        = 印刷模板
#2. 示例拆分

controllers/roadController.js

js
const roadService = require('../services/roadService');

exports.listRoads = (req, res) => {
  const roads = roadService.list();
  res.json(roads);
};

exports.getRoad = (req, res, next) => {
  const road = roadService.getById(Number(req.params.id));

  if (!road) {
    const err = new Error('道路不存在');
    err.status = 404;
    return next(err);
  }

  res.json(road);
};

services/roadService.js

js
const roads = [
  { id: 1, name: '中山主路', status: 'open' },
  { id: 2, name: '复兴大道', status: 'repairing' }
];

exports.list = () => roads;

exports.getById = (id) => roads.find(item => item.id === id);

routes/roadRoutes.js

js
const express = require('express');
const roadController = require('../controllers/roadController');

const router = express.Router();

router.get('/', roadController.listRoads);
router.get('/:id', roadController.getRoad);

module.exports = router;

app.js

js
const express = require('express');
const roadRoutes = require('./routes/roadRoutes');
const notFound = require('./middlewares/notFound');
const errorHandler = require('./middlewares/errorHandler');

const app = express();

app.use(express.json());
app.use('/api/roads', roadRoutes);
app.use(notFound);
app.use(errorHandler);

module.exports = app;
#3. 为什么这样拆

因为你要让城市地图清晰:

  • 路怎么走,看 routes
  • 这个窗口干什么,看 controllers
  • 业务规则在哪,看 services
  • 出了事怎么统一处理,看 middlewares

这比“所有东西全塞进 app.js”强太多。