您现在的位置是:网站首页 > 项目结构与目录组织规范文章详情
项目结构与目录组织规范
陈川
【
Node.js
】
21053人已围观
6360字
Express框架作为Node.js中最流行的Web应用框架之一,其项目结构与目录组织规范直接影响代码的可维护性和扩展性。合理的目录划分和模块化设计能够提升团队协作效率,降低后期维护成本。
核心目录结构
典型的Express项目通常包含以下核心目录:
project-root/
├── bin/ # 启动脚本
├── config/ # 配置文件
├── public/ # 静态资源
├── routes/ # 路由定义
├── models/ # 数据模型
├── controllers/ # 业务逻辑
├── middlewares/ # 自定义中间件
├── views/ # 模板文件
├── tests/ # 测试代码
├── app.js # 应用入口
└── package.json # 项目配置
入口文件设计
应用入口文件app.js
应当保持简洁,主要完成以下工作:
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
// 路由引入
const indexRouter = require('./routes/index');
const apiRouter = require('./routes/api');
const app = express();
// 中间件配置
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// 路由挂载
app.use('/', indexRouter);
app.use('/api', apiRouter);
// 错误处理中间件
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({ error: err.message });
});
module.exports = app;
路由组织规范
路由文件应当按功能模块拆分,避免将所有路由定义集中在单个文件中:
// routes/api/users.js
const express = require('express');
const router = express.Router();
const usersController = require('../controllers/users');
router.get('/', usersController.list);
router.post('/', usersController.create);
router.get('/:id', usersController.show);
router.put('/:id', usersController.update);
router.delete('/:id', usersController.delete);
module.exports = router;
然后在主路由文件中进行聚合:
// routes/index.js
const express = require('express');
const router = express.Router();
router.use('/api/users', require('./api/users'));
router.use('/api/products', require('./api/products'));
module.exports = router;
控制器设计原则
控制器应当保持精简,主要处理HTTP请求和响应:
// controllers/users.js
const User = require('../models/user');
exports.list = async (req, res, next) => {
try {
const users = await User.find();
res.json(users);
} catch (err) {
next(err);
}
};
exports.create = async (req, res, next) => {
try {
const user = new User(req.body);
await user.save();
res.status(201).json(user);
} catch (err) {
next(err);
}
};
中间件管理
自定义中间件应当集中存放在middlewares
目录中:
// middlewares/auth.js
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
const token = req.header('Authorization');
if (!token) return res.status(401).send('Access denied');
try {
const verified = jwt.verify(token, process.env.JWT_SECRET);
req.user = verified;
next();
} catch (err) {
res.status(400).send('Invalid token');
}
};
环境配置管理
配置文件应当按环境区分,并通过环境变量加载:
// config/default.js
module.exports = {
port: process.env.PORT || 3000,
db: {
uri: process.env.DB_URI || 'mongodb://localhost:27017/dev_db'
},
jwt: {
secret: process.env.JWT_SECRET || 'default_secret'
}
};
// config/production.js
module.exports = {
db: {
uri: process.env.DB_URI
},
jwt: {
secret: process.env.JWT_SECRET
}
};
静态资源管理
静态资源应当分类存放:
public/
├── images/ # 图片资源
├── js/ # 客户端JavaScript
├── css/ # 样式表
└── uploads/ # 用户上传文件
测试目录结构
测试文件应当与被测模块保持相同结构:
tests/
├── unit/ # 单元测试
│ ├── controllers/
│ ├── models/
│ └── middlewares/
└── integration/ # 集成测试
├── api/
└── routes/
视图模板组织
使用模板引擎时,视图文件应当模块化:
views/
├── layouts/ # 布局文件
│ └── main.hbs
├── partials/ # 公共组件
│ ├── header.hbs
│ └── footer.hbs
└── pages/ # 具体页面
├── home.hbs
└── users/
├── list.hbs
└── detail.hbs
模块化实践
大型项目可以考虑功能模块划分:
modules/
├── user/ # 用户模块
│ ├── controllers/
│ ├── models/
│ ├── routes/
│ └── tests/
└── product/ # 产品模块
├── controllers/
├── models/
├── routes/
└── tests/
日志管理
日志文件应当按类型和日期组织:
logs/
├── access/ # 访问日志
│ ├── 2023-08-01.log
│ └── 2023-08-02.log
└── error/ # 错误日志
├── 2023-08-01.log
└── 2023-08-02.log
文档规范
项目文档应当统一存放:
docs/
├── api.md # API文档
├── db.md # 数据库设计
└── setup.md # 环境搭建
工具脚本管理
自定义脚本应当分类存放:
scripts/
├── db/ # 数据库脚本
│ ├── migrate.js
│ └── seed.js
└── deploy/ # 部署脚本
├── staging.sh
└── production.sh
环境变量管理
敏感配置应当通过.env
文件管理:
# .env.example
DB_URI=mongodb://localhost:27017/dev_db
JWT_SECRET=your_jwt_secret
PORT=3000
代码风格统一
项目应当包含统一的代码风格配置:
// .eslintrc.json
{
"extends": "airbnb-base",
"rules": {
"linebreak-style": ["error", "unix"],
"indent": ["error", 2],
"quotes": ["error", "single"]
}
}
构建产物管理
前端构建产物应当统一输出:
dist/ # 构建输出目录
├── assets/ # 编译后的静态资源
│ ├── js/
│ ├── css/
│ └── images/
└── index.html # 生成的HTML文件
异常处理规范
全局异常应当统一处理:
// middlewares/errorHandler.js
module.exports = (err, req, res, next) => {
console.error(err.stack);
if (err instanceof CustomError) {
return res.status(err.statusCode).json({
error: err.message,
details: err.details
});
}
res.status(500).json({
error: 'Internal Server Error'
});
};
数据库迁移管理
数据库变更应当通过迁移脚本管理:
// scripts/db/migrate/20230801-create-users.js
exports.up = async (db) => {
await db.createCollection('users', {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["username", "email"],
properties: {
username: { bsonType: "string" },
email: { bsonType: "string" }
}
}
}
});
};
exports.down = async (db) => {
await db.collection('users').drop();
};
依赖管理规范
第三方依赖应当分类管理:
// package.json
{
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.3.1"
},
"devDependencies": {
"eslint": "^8.45.0",
"jest": "^29.6.1"
}
}
自动化任务配置
常用任务应当通过npm scripts定义:
// package.json
{
"scripts": {
"start": "node bin/www",
"dev": "nodemon bin/www",
"test": "jest",
"lint": "eslint .",
"migrate": "node scripts/db/migrate.js"
}
}
上一篇: 中间件的最佳实践总结
下一篇: 环境配置与多环境管理