Project structure and directory organization standards
Project Structure and Directory Organization Standards
The structure and directory organization of an Express project are crucial for code maintainability and scalability. A well-organized directory structure helps team members quickly understand the project architecture, reduces communication overhead, and facilitates future feature expansion and maintenance.
Basic Directory Structure
A typical basic directory structure for an Express project is as follows:
project-root/
├── node_modules/
├── src/
│ ├── controllers/
│ ├── models/
│ ├── routes/
│ ├── middlewares/
│ ├── services/
│ ├── utils/
│ ├── config/
│ ├── public/
│ ├── views/
│ └── app.js
├── tests/
├── .env
├── .gitignore
├── package.json
└── README.md
Core Directory Details
controllers Directory
Stores the business logic processing layer, responsible for receiving request parameters, invoking service layers to handle business logic, and returning responses:
// src/controllers/userController.js
const userService = require('../services/userService');
exports.getUser = async (req, res) => {
try {
const user = await userService.getUserById(req.params.id);
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
models Directory
Defines data models and database interaction logic, often used with ORMs like Sequelize or Mongoose:
// src/models/userModel.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
}, { timestamps: true });
module.exports = mongoose.model('User', userSchema);
routes Directory
Defines API routes and directs requests to the corresponding controllers:
// src/routes/userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.get('/:id', userController.getUser);
router.post('/', userController.createUser);
router.put('/:id', userController.updateUser);
module.exports = router;
Advanced Directory Organization
Feature-Based Modularization
For large projects, a feature-based modular approach can be adopted:
src/
├── modules/
│ ├── auth/
│ │ ├── auth.controller.js
│ │ ├── auth.model.js
│ │ ├── auth.routes.js
│ │ └── auth.service.js
│ ├── user/
│ │ ├── user.controller.js
│ │ ├── user.model.js
│ │ ├── user.routes.js
│ │ └── user.service.js
│ └── product/
│ ├── product.controller.js
│ ├── product.model.js
│ ├── product.routes.js
│ └── product.service.js
├── core/
│ ├── database.js
│ ├── server.js
│ └── middleware.js
└── app.js
Configuration Management
Centralize configuration management with support for different environments:
// src/config/index.js
require('dotenv').config();
module.exports = {
app: {
port: process.env.PORT || 3000,
env: process.env.NODE_ENV || 'development'
},
db: {
uri: process.env.MONGODB_URI,
options: {
useNewUrlParser: true,
useUnifiedTopology: true
}
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: '24h'
}
};
Middleware Organization
Middleware should be organized separately for reusability and management:
// src/middlewares/authMiddleware.js
const jwt = require('jsonwebtoken');
const config = require('../config');
module.exports = (req, res, next) => {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'Access denied' });
}
try {
const decoded = jwt.verify(token, config.jwt.secret);
req.user = decoded;
next();
} catch (error) {
res.status(400).json({ error: 'Invalid token' });
}
};
Utility Organization
Centralize common utility functions:
// src/utils/response.js
exports.success = (res, data, status = 200) => {
res.status(status).json({
success: true,
data
});
};
exports.error = (res, message, status = 400) => {
res.status(status).json({
success: false,
error: message
});
};
Application Entry File
The main application file should remain concise, primarily handling initialization:
// src/app.js
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const config = require('./config');
const routes = require('./routes');
const app = express();
// Middleware
app.use(cors());
app.use(helmet());
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Routes
app.use('/api', routes);
// Error handling
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Internal Server Error' });
});
module.exports = app;
Test Directory Structure
The test directory should mirror the source code structure:
tests/
├── unit/
│ ├── controllers/
│ ├── models/
│ └── services/
├── integration/
│ ├── routes/
│ └── middlewares/
└── e2e/
├── api/
└── auth/
Static Resource Management
Static resources should be organized under the public directory:
public/
├── images/
├── css/
├── js/
└── uploads/
View Template Organization
If using a template engine, organize view files logically:
views/
├── layouts/
│ └── main.hbs
├── partials/
│ ├── header.hbs
│ └── footer.hbs
├── home/
│ └── index.hbs
└── user/
├── profile.hbs
└── edit.hbs
Environment Variable Management
Use .env files to manage environment variables and load them via dotenv:
# .env
PORT=3000
NODE_ENV=development
MONGODB_URI=mongodb://localhost:27017/myapp
JWT_SECRET=mysecretkey
Package Management Standards
Organize scripts and dependencies properly in package.json:
{
"scripts": {
"start": "node src/app.js",
"dev": "nodemon src/app.js",
"test": "jest",
"lint": "eslint .",
"format": "prettier --write ."
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.0.3"
},
"devDependencies": {
"nodemon": "^2.0.22",
"eslint": "^8.36.0",
"prettier": "^2.8.7"
}
}
Documentation and Instructions
The project root should include necessary documentation files:
- README.md: Project overview, installation instructions, usage guide
- CHANGELOG.md: Version change log
- API_DOC.md: API documentation
- .editorconfig: Unified editor configuration
- .eslintrc: Code style check configuration
- .prettierrc: Code formatting configuration
Large-Scale Project Extended Structure
For enterprise-level applications, consider a more complex structure:
src/
├── api/
│ ├── v1/
│ │ ├── modules/
│ │ └── routes.js
│ └── v2/
│ ├── modules/
│ └── routes.js
├── core/
│ ├── exceptions/
│ ├── logging/
│ ├── database/
│ └── utils/
├── jobs/
├── migrations/
├── seeders/
└── app.js
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:中间件的最佳实践总结
下一篇:环境配置与多环境管理