Router — alohida fayllarga bo'lish, modullar
Muammodan boshlaylik
Loyiha o'sib boradi. app.js faylida foydalanuvchilar, mahsulotlar, buyurtmalar, to'lovlar — barchasi bir joyda:
app.get('/users', ...);
app.post('/users', ...);
app.get('/users/:id', ...);
app.put('/users/:id', ...);
app.delete('/users/:id', ...);
app.get('/products', ...);
app.post('/products', ...);
// ... yana 50 ta route
Bir fayl — 500 qator. Qaysi route qayerda ekanini topish qiyin. Jamoa bilan ishlashda har kim bir xil faylni o'zgartiradi — konfliktlar ko'p.
Router bu muammoni hal qiladi: har bir resurs uchun alohida fayl, alohida router.
Router nima?
express.Router() — mini Express ilovasi. Unga route va middleware qo'shiladi, keyin asosiy app ga ulanadi.
Hayotiy o'xshatma: katta kompaniyada har bir bo'lim o'z ichki qoidalariga ega. HR bo'limi — o'z jarayonlari, moliya bo'limi — o'z jarayonlari. Direktor (app) ularni birlashtiradi, lekin har bir bo'lim mustaqil ishlaydi. Router — o'sha bo'lim.
Router yaratish
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.json([{ id: 1, name: 'Ali' }]);
});
router.get('/:id', (req, res) => {
res.json({ id: req.params.id });
});
router.post('/', (req, res) => {
res.status(201).json(req.body);
});
module.exports = router;
// app.js
const express = require('express');
const usersRouter = require('./routes/users');
const app = express();
app.use(express.json());
app.use('/users', usersRouter); // /users prefiksi bilan ulash
app.listen(3000);
Endi usersRouter dagi barcha route lar /users prefiksi bilan ishlaydi:
router.get('/')→GET /usersrouter.get('/:id')→GET /users/:idrouter.post('/')→POST /users
Router ichida /users yozilmaydi — prefiks app.use da bir marta beriladi.
Loyiha tuzilmasi
Router bilan loyiha quyidagi ko'rinishga keladi:
src/
├── routes/
│ ├── users.js
│ ├── products.js
│ └── orders.js
├── controllers/
│ ├── users.controller.js
│ └── products.controller.js
├── middleware/
│ └── auth.js
└── app.js
Har bir fayl — o'z vazifasi. routes/users.js — faqat foydalanuvchi route lari. controllers/users.controller.js — faqat foydalanuvchi logikasi.
Controller — logikani route dan ajratish
Route faylida ham logika yozish mumkin, lekin bu ham o'sib ketadi. Yaxshi amaliyot — route faqat "qaysi handler" ni ko'rsatadi, handler alohida faylda:
// controllers/users.controller.js
const users = [
{ id: 1, name: 'Ali' },
{ id: 2, name: 'Vali' },
];
exports.getAll = (req, res) => {
res.json(users);
};
exports.getOne = (req, res) => {
const user = users.find(u => u.id === +req.params.id);
if (!user) return res.status(404).json({ message: 'Topilmadi' });
res.json(user);
};
exports.create = (req, res) => {
const user = { id: Date.now(), ...req.body };
users.push(user);
res.status(201).json(user);
};
// routes/users.js
const express = require('express');
const router = express.Router();
const controller = require('../controllers/users.controller');
router.get('/', controller.getAll);
router.get('/:id', controller.getOne);
router.post('/', controller.create);
module.exports = router;
Route fayli endi faqat "qaysi URL — qaysi handler" ni ko'rsatadi. Logika controller da. Har biri o'z joyida.
Router da middleware
Router ga middleware qo'shilsa — faqat o'sha router dagi route larga ta'sir qiladi:
// routes/admin.js
const express = require('express');
const router = express.Router();
const { authenticate, requireRole } = require('../middleware/auth');
// Bu router dagi barcha route lar uchun:
router.use(authenticate);
router.use(requireRole('admin'));
router.get('/stats', (req, res) => res.json({ users: 100 }));
router.delete('/users/:id', (req, res) => res.json({ deleted: true }));
module.exports = router;
// app.js
app.use('/admin', adminRouter); // /admin/* — hammasi auth + admin rol talab qiladi
app.use('/users', usersRouter); // /users/* — ochiq
/admin/* ga kelgan barcha so'rovlar authenticate va requireRole('admin') dan o'tadi. /users/* esa ochiq.
app.js — tartibli ko'rinish
Barcha router lar ulangandan keyin app.js qisqa va tushunarli bo'ladi:
const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const usersRouter = require('./routes/users');
const productsRouter = require('./routes/products');
const ordersRouter = require('./routes/orders');
const app = express();
// Global middleware
app.use(morgan('dev'));
app.use(cors());
app.use(express.json());
// Route lar
app.use('/users', usersRouter);
app.use('/products', productsRouter);
app.use('/orders', ordersRouter);
// 404
app.use((req, res) => {
res.status(404).json({ message: 'Topilmadi' });
});
// Error middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.statusCode || 500).json({ message: err.message || 'Server xatosi' });
});
module.exports = app;
app.js da logika yo'q — faqat sozlash. Har bir resurs o'z faylida.
Tez-tez uchraydigan xatolar
Prefiks ikki marta yozish:
// routes/users.js da:
router.get('/users', ...); // '/users' yozildi
// app.js da:
app.use('/users', usersRouter); // yana '/users'
// Natija: GET /users/users — noto'g'ri!
Router ichida prefiks yozilmaydi — u app.use da bir marta beriladi.
module.exports unutish:
// routes/users.js
const router = express.Router();
router.get('/', ...);
// module.exports = router; — unutildi!
// app.js da:
const usersRouter = require('./routes/users');
app.use('/users', usersRouter); // usersRouter = {} — bo'sh ob'ekt
Xulosa
Router — Express ilovasini kichik bo'laklarga ajratish uchun. Har bir resurs o'z faylida, o'z route lari bilan. app.use('/prefix', router) bilan asosiy ilovaga ulanadi.
Controller — logikani route dan ajratadi. Route faqat "qaysi URL — qaysi handler" ni ko'rsatadi.
Natija: katta loyihada ham har bir fayl kichik, tushunarli va o'z vazifasiga ega.
Keyingi dars
13-dars: PostgreSQL — pg moduli, connection pool