Modules — Feature, Shared, Global, Dynamic
Loyiha o'sib boradi
Siz kichik loyiha boshladingiz. Avvaliga hammasi AppModule da edi — bir controller, bir service. Ishladi. Lekin loyiha o'sdi — foydalanuvchilar, mahsulotlar, buyurtmalar, to'lovlar paydo bo'ldi. Hammasi bitta modulda — bu endi boshqarib bo'lmaydigan darajaga keldi.
Aynan shu paytda Module tizimi qutqaradi.
NestJS da modul — bu loyihaning bir bo'lagi. Har bir bo'lak o'z ichida yopiq, o'z vazifasiga ega. Boshqa bo'laklar bilan faqat kerak bo'lganda bog'lanadi.
Modul qanday ko'rinadi?
import { Module } from "@nestjs/common";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";
@Module({
imports: [], // boshqa modullardan nima kerak
controllers: [], // bu modulning controllerlari
providers: [], // bu modulning servicelari
exports: [], // boshqa modullarga nima berish
})
export class UsersModule {}
@Module decorator to'rtta maydon qabul qiladi. Hozircha ularni yodlab olmang — ish jarayonida o'zlari yodlanadi.
Feature Module — eng ko'p ishlatiladigan tur
Feature Module — bu loyihaning bitta funksiyasiga bag'ishlangan modul. "Foydalanuvchilar" funksiyasi — UsersModule. "Mahsulotlar" funksiyasi — ProductsModule.
Keling, to'liq misol ko'ramiz. Faraz qiling, e-commerce loyiha yozyapsiz:
src/
├── users/
│ ├── users.module.ts
│ ├── users.controller.ts
│ └── users.service.ts
├── products/
│ ├── products.module.ts
│ ├── products.controller.ts
│ └── products.service.ts
├── orders/
│ ├── orders.module.ts
│ ├── orders.controller.ts
│ └── orders.service.ts
└── app.module.ts
Har bir papka — alohida dunyo. users papkasidagi fayllar faqat foydalanuvchilar bilan ishlaydi. products — faqat mahsulotlar bilan. Tartib bor, aniqlik bor.
CLI bilan yaratish:
nest g mo users # users.module.ts
nest g co users --no-spec # users.controller.ts
nest g s users --no-spec # users.service.ts
--no-spec — test fayllarini yaratmaslik uchun. Har bir buyruq faylni yaratib, users.module.ts ga avtomatik ulaydi.
Modullarni bog'lash — imports va exports
Endi amaliy holat: OrdersService buyurtma yaratayotganda foydalanuvchini tekshirishi kerak. Buning uchun UsersService ga murojaat qilishi lozim.
Lekin UsersService — UsersModule ichida. OrdersModule uni ko'rmaydi. Qanday hal qilamiz?
1-qadam: UsersModule da UsersService ni export qilamiz:
// users/users.module.ts
import { Module } from "@nestjs/common";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";
@Module({
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService], // ← boshqalarga ochib beramiz
})
export class UsersModule {}
2-qadam: OrdersModule da UsersModule ni import qilamiz:
// orders/orders.module.ts
import { Module } from "@nestjs/common";
import { OrdersController } from "./orders.controller";
import { OrdersService } from "./orders.service";
import { UsersModule } from "../users/users.module";
@Module({
imports: [UsersModule], // ← UsersModule ni olib kelamiz
controllers: [OrdersController],
providers: [OrdersService],
})
export class OrdersModule {}
3-qadam: Endi OrdersService UsersService ni erkin ishlatishi mumkin:
// orders/orders.service.ts
import { Injectable } from "@nestjs/common";
import { UsersService } from "../users/users.service";
@Injectable()
export class OrdersService {
constructor(private readonly usersService: UsersService) {}
create(userId: number, productId: number) {
const user = this.usersService.findOne(userId);
if (!user) {
return { error: "Foydalanuvchi topilmadi" };
}
return {
orderId: Math.random(),
user: user.name,
productId,
status: "yaratildi",
};
}
}
💡
exportsga yozmagan Service — faqat o'z moduli ichida ko'rinadi. Bu yaxshi narsa — keraksiz narsalarni yashirasiz, faqat keraklilarni ochasiz.
Shared Module — umumiy modullar
Ba'zi narsalar butun loyiha bo'ylab kerak bo'ladi. Masalan, LoggerService — hamma joyda loglash kerak. HelperService — umumiy yordamchi funksiyalar.
Buning uchun Shared Module yaratiladi:
// shared/shared.module.ts
import { Module } from "@nestjs/common";
import { LoggerService } from "./logger.service";
import { HelperService } from "./helper.service";
@Module({
providers: [LoggerService, HelperService],
exports: [LoggerService, HelperService], // hammaga ochiq
})
export class SharedModule {}
Keyin har bir modulda import qilinadi:
// users/users.module.ts
import { SharedModule } from "../shared/shared.module";
@Module({
imports: [SharedModule],
// ...
})
export class UsersModule {}
Endi UsersService, ProductsService, OrdersService — barchasi LoggerService va HelperService ni ishlatishi mumkin.
Global Module — hamma joyda avtomatik
SharedModule ni har bir modulga alohida import qilish — zerikarli. Agar 20 ta modul bo'lsa, 20 ta joyga yozish kerakmi?
Buning uchun Global Module bor:
// shared/shared.module.ts
import { Global, Module } from "@nestjs/common";
import { LoggerService } from "./logger.service";
@Global() // ← shu decorator yetarli
@Module({
providers: [LoggerService],
exports: [LoggerService],
})
export class SharedModule {}
@Global() decorator qo'yilgandan keyin — bu modulni faqat AppModule da bir marta import qilasiz:
// app.module.ts
import { Module } from "@nestjs/common";
import { SharedModule } from "./shared/shared.module";
import { UsersModule } from "./users/users.module";
import { ProductsModule } from "./products/products.module";
@Module({
imports: [
SharedModule, // bir marta — hammaga yetadi
UsersModule,
ProductsModule,
],
})
export class AppModule {}
Endi UsersModule, ProductsModule va boshqa barcha modullarda LoggerService import qilmasdan ishlatish mumkin.
⚠️
@Global()ni ehtiyotkorlik bilan ishlating. Hamma narsani global qilib qo'ysangiz — modullar orasidagi bog'liqlikni kuzatish qiyinlashadi. Faqat haqiqatan hamma joyda kerakli narsalargina global bo'lsin.
Dynamic Module — moslashuvchan modullar
Ba'zan modul yaratilayotganda unga sozlamalar berish kerak bo'ladi. Masalan, ma'lumotlar bazasi moduli — ulanish ma'lumotlarini olishi kerak. Email moduli — SMTP server ma'lumotlarini olishi kerak.
Buning uchun Dynamic Module ishlatiladi:
// database/database.module.ts
import { Module, DynamicModule } from "@nestjs/common";
import { DatabaseService } from "./database.service";
@Module({})
export class DatabaseModule {
static forRoot(options: {
host: string;
port: number;
database: string;
}): DynamicModule {
return {
module: DatabaseModule,
providers: [
{
provide: "DB_OPTIONS", // token — nom sifatida
useValue: options, // qiymat
},
DatabaseService,
],
exports: [DatabaseService],
};
}
}
AppModule da ishlatish:
// app.module.ts
@Module({
imports: [
DatabaseModule.forRoot({
host: "localhost",
port: 5432,
database: "mydb",
}),
],
})
export class AppModule {}
DatabaseService ichida bu sozlamalarni olish:
// database/database.service.ts
import { Injectable, Inject } from "@nestjs/common";
@Injectable()
export class DatabaseService {
constructor(
@Inject("DB_OPTIONS")
private options: {
host: string;
port: number;
database: string;
},
) {
console.log(
`${options.host}:${options.port}/${options.database} ga ulanmoqda`,
);
}
}
💡 Real loyihalarda siz
DatabaseModule.forRoot()ni o'zingiz yozmaysiz —TypeORM,Mongoose,Prismakabi kutubxonalar bu pattern ni tayyor holda beradi. Lekin ichida qanday ishlashini tushunish muhim.
AppModule — bosh modul
Barcha modullar oxir-oqibat AppModule ga ulanadi. U loyihaning "ildizi":
// app.module.ts
import { Module } from "@nestjs/common";
import { UsersModule } from "./users/users.module";
import { ProductsModule } from "./products/products.module";
import { OrdersModule } from "./orders/orders.module";
import { SharedModule } from "./shared/shared.module";
@Module({
imports: [SharedModule, UsersModule, ProductsModule, OrdersModule],
})
export class AppModule {}
AppModule da controller va provider kamdan-kam yoziladi — u faqat modullarni birlashtiradi.
To'liq ko'rinish
AppModule
├── SharedModule (Global)
│ └── LoggerService → hamma joyda ishlatiladi
├── UsersModule
│ ├── UsersController
│ └── UsersService → export qilingan
├── ProductsModule
│ ├── ProductsController
│ └── ProductsService
└── OrdersModule
├── OrdersController
├── OrdersService → UsersService ni ishlatadi
└── imports: [UsersModule]
Har bir modul o'z ichida yopiq. Faqat exports orqali ochilgan narsalar tashqaridan ko'rinadi.
Xulosa
Module — bu NestJS loyihasining qurilish g'ishtlari. Har bir g'isht o'z ichida mustaqil, lekin boshqalari bilan bog'lanishi mumkin.
Eslab qoling:
- Feature Module → bitta funksiya uchun (
UsersModule,ProductsModule) - Shared Module → umumiy narsalar uchun,
exportsbilan ochiladi - Global Module →
@Global()— bir marta import, hamma joyda ishlatish - Dynamic Module → sozlamalar bilan yaratilgan modul (
forRoot()) imports→ boshqa moduldan foydalanishexports→ o'z ichidagi narsani boshqalarga berish
Keyingi dars
5-dars: DTO + Class-validator + Class-transformer