index.js
quá lớn hoặc file đặt lung tung là dấu hiệu dự án thiếu tổ chức, gây khó khăn khi mở rộng và bảo trì.authController.js
và authRoutes.js
. Điều này giúp mã nguồn rõ ràng và dễ điều hướng.// middlewares/logger.jsmodule.exports = (req, res, next) => { console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); next();};
// index.jsconst logger = require('./middlewares/logger');app.use(logger);
app.use((req, res, next) => { // anonymous logger});
const helmet = require('helmet');const cors = require('cors');const mongoSanitize = require('express-mongo-sanitize');
app.use(helmet());app.use(cors());app.use(mongoSanitize());
express-rate-limit
:const rateLimit = require('express-rate-limit');
const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 phút max: 100, message: 'Quá nhiều yêu cầu từ IP này, vui lòng thử lại sau.',});
app.use(limiter);
.env
PORT=5000MONGO_URI=mongodb://localhost:27017/myapp
dotenv
require('dotenv').config();mongoose.connect(process.env.MONGO_URI);
fs.readFile('a.txt', (err, data) => { fs.readFile('b.txt', (err2, data2) => { // tiếp tục... });});
const util = require('util');const readFile = util.promisify(fs.readFile);const data = await readFile('a.txt');
router.get('/user/:id', async (req, res) => { const user = await User.findById(req.params.id); res.json(user);});
catchAsync
:// utils/catchAsync.jsmodule.exports = fn => (req, res, next) => { fn(req, res, next).catch(next);};
// routerrouter.get('/user/:id', catchAsync(async (req, res) => { const user = await User.findById(req.params.id); res.json(user);}));
app.use('/api/v1/users', userRoutes);
v1/
và v2/
để dễ quản lý.const Joi = require('joi');const userSchema = Joi.object({ email: Joi.string().email().required(), password: Joi.string().min(6).required(),});
router.post('/register', async (req, res, next) => { const { error } = userSchema.validate(req.body); if (error) return res.status(400).json({ error: error.details[0].message });});
const morgan = require('morgan');app.use(morgan('dev'));
// logger.jsconst winston = require('winston');
module.exports = winston.createLogger({ level: 'info', transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), // có thể thêm Console hoặc các file log khác ],});
Tiêu chí | Công cụ/Phương pháp | Lợi ích |
---|---|---|
Xử lý lỗi trung tâm | Middleware app.use(errHandler) | Quản lý lỗi tập trung |
Xác thực & Sanitization | Joi, Yup, Zod | Tránh dữ liệu sai hoặc độc hại |
Kiểm thử | Jest, Supertest | Đảm bảo độ ổn định |
Tài liệu API | Swagger, Postman | Tạo docs tự động |
Mã chuẩn | ESLint, Prettier | Nhất quán, dễ đọc |
Giám sát | New Relic, Sentry, PM2 | Phát hiện lỗi & giám sát hiệu quả |