In production backend applications containing dozens or hundreds of endpoints, defining all routes inside a single server.js file leads to unmaintainable spaghetti code. Professional developers separate routing logic into dedicated Router files and encapsulate business operations inside Controller classes following the MVC (Model-View-Controller) architecture.
my-api/
├── controllers/
│ └── studentController.js // Business logic & response handling
├── routes/
│ └── studentRoutes.js // URL route endpoints definition
├── models/
│ └── studentModel.js // Database schema
├── middleware/
│ └── authMiddleware.js // JWT / API key verification
└── server.js // App initialization & mounting
studentController.js// controllers/studentController.js
// Simulated in-memory database
let students = [
{ id: 1, name: 'Amit Kumar', rollNo: 'BCA-101', course: 'Computer Science' },
{ id: 2, name: 'Priya Sharma', rollNo: 'BCA-102', course: 'Information Technology' }
];
// GET /api/students - List all students
exports.getAllStudents = (req, res) => {
res.status(200).json({
success: true,
count: students.length,
data: students
});
};
// GET /api/students/:id - Get single student by ID
exports.getStudentById = (req, res) => {
const studentId = parseInt(req.params.id);
const student = students.find(s => s.id === studentId);
if (!student) {
return res.status(404).json({ success: false, error: 'Student not found' });
}
res.status(200).json({ success: true, data: student });
};
// POST /api/students - Create new student
exports.createStudent = (req, res) => {
const { name, rollNo, course } = req.body;
if (!name || !rollNo) {
return res.status(400).json({ success: false, error: 'Name and RollNo are required' });
}
const newStudent = { id: students.length + 1, name, rollNo, course: course || 'BCA' };
students.push(newStudent);
res.status(201).json({ success: true, data: newStudent });
};
studentRoutes.js// routes/studentRoutes.js
const express = require('express');
const router = express.Router();
const studentController = require('../controllers/studentController');
// Route Chaining using router.route()
router
.route('/')
.get(studentController.getAllStudents)
.post(studentController.createStudent);
router
.route('/:id')
.get(studentController.getStudentById);
module.exports = router;
server.js// server.js
const express = require('express');
const studentRoutes = require('./routes/studentRoutes');
const app = express();
app.use(express.json());
// Mount router under the /api/students path prefix
app.use('/api/students', studentRoutes);
app.listen(3000, () => console.log('Server running on port 3000'));
Boost your server-side JavaScript proficiency by studying these closely connected core modules:
Chain route-level middleware for authorization.
Implement full CRUD routes in controller files.
Review basic app.get and app.post setups.