Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. @Module ning to'rt maydoni
- 2.1 Jadval
- 2.2 Modul daraxti
- 3. Ko'rinish qoidasi — haqiqiy tajriba
- 3.1 Tajriba sharti
- 3.2 exports siz
- 3.3 exports bilan — va bitta nusxa
- 3.4 Tuzoq: ikki joyda providers
- 3.5 providers da yo'q narsani eksport qilish
- 4. JS modelida ko'rinish qoidasi
- 5. Modul turlari
- 5.1 Feature modul
- 5.2 @Global modul
- 5.3 Qayta eksport (re-export)
- 5.4 Dinamik modul — bir qarash
- 6. Modul fayl importi bilan bir narsa emas
- 7. Ishga tushish logida modullar
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): ko'rinadimi?
- 2-mashq (o'rta): modelga @Global qo'shing
- 3-mashq (qiyin): modul tekshiruvchisi
- 10. Loyiha qadami: modul qutilari
- 11. Real ishda
- Xulosa
- Manbalar
NestJS modullari: @Module, imports, providers, exports va @Global
Qisqacha: Modul —
@Module()dekoratorli klass:controllers(marshrutlar),providers(Nest yaratadigan obyektlar),imports(boshqa modullar) vaexports(tashqariga beriladigan provider'lar). Provider sukut bo'yicha faqat o'z modulida ko'rinadi. Boshqa modul uni ishlatishi uchun ikki shart: egasi uniexportsga yozadi, ishlatuvchi esa egasiniimportsga yozadi. Shart bajarilmasa, Nest ilova ishga tushayotgandaNest can't resolve dependencies…xatosini beradi.
Bu darsda
@Modulening to'rt maydonini va har biri nimani hal qilishini bilasiz.- Provider qachon boshqa modulda ko'rinishini va qachon ko'rinmasligini haqiqiy xato bilan tushuntirasiz.
- Shared,
@Globalva qayta eksport qiluvchi (re-export) modullarni farqlaysiz. - Bir provider'ni ikki modulga yozib qo'yish nega ikki nusxa berishini o'z ko'zingiz bilan ko'rasiz.
vazifalar-apini modullarga bo'lishni boshlaysiz.
Oldin bilishingiz kerak: NestJS nima va nega, Nest CLI va loyiha tuzilmasi, express.Router va qatlamli loyiha tuzilmasi, Nega modullar va ESM export.
O'tgan darsda vazifalar-api ga Nest skeleti qo'shildi: bitta AppModule va GET /salom. Endi haqiqiy marshrutlar keladi. Ularni bitta modulga to'kib tashlamaymiz — avval "qaysi kod qaysi qutida" degan savolga javob beramiz.
1. Nega bu kerak?
25-qismda kodni feature-folder bo'yicha ajratgandik: vazifalar/, eksport/, umumiy/ (qatlamlar darsi). Bu tartib faqat kelishuv edi. eksport/eksport.ts xohlasa vazifalar/xizmat.ts ning ichki funksiyasini import qila olardi. Hech kim to'xtatmasdi.
Loyiha kattalashganda bunday "yashirin yo'laklar" ko'payadi. Bir papkadagi o'zgarish boshqasini kutilmaganda buzadi. Kim nimaga tayanishini bilish uchun butun kodni o'qish kerak bo'ladi.
Nest moduli — kelishuvni qoidaga aylantiradi. Har modul o'z ichidagi obyektlarni sukut bo'yicha yashiradi. Tashqariga faqat ochiq e'lon qilinganlari chiqadi.
O'xshatish: ko'p qavatli uydagi xonadonlar. Har xonadonning o'z oshxonasi, o'z jihozlari bor. Qo'shni sizning muzlatkichingizdan foydalana olmaydi. Lekin uyning umumiy liftini hamma ishlatadi — u "umumiy" deb e'lon qilingan. Nest'da xonadon — modul, jihoz — provider, lift — eksport qilingan provider.
2. @Module ning to'rt maydoni
2.1 Jadval
| Maydon | Nima yoziladi | Savol |
|---|---|---|
controllers |
shu modul marshrutlari | "Qaysi HTTP yo'llar shu yerda?" |
providers |
Nest yaratadigan klasslar | "Nimani shu modul o'zi yaratadi?" |
imports |
boshqa modullar | "Kimning eksportlari kerak?" |
exports |
o'z provider'laridan bir qismi | "Tashqariga nimani beraman?" |
nest g resource yaratgan modul (o'tgan darsda ko'rdik) — eng sodda shakl:
@Module({
controllers: [MahsulotlarController],
providers: [MahsulotlarService],
})
export class MahsulotlarModule {}Bu yerda exports yo'q. Ya'ni MahsulotlarService faqat shu modul ichida — MahsulotlarController uchun. Boshqa modul uni ololmaydi.
Klassning o'zi bo'sh: {}. Hamma ma'lumot dekoratorda. Klass faqat tashuvchi — Nest uning ustidagi metama'lumotni o'qiydi. O'tgan darsdagi ESLint qoidasi (allowWithDecorator) shu uchun kerak edi.
2.2 Modul daraxti
Har Nest ilovasida bitta ildiz modul bor — odatda AppModule. NestFactory.create(AppModule) undan boshlaydi, imports bo'ylab pastga tushadi va butun daraxtni yig'adi. Daraxtga ulanmagan modul ilovada umuman yo'q.
Ko'chish tugagach vazifalar-api ning daraxti shunday bo'ladi:
flowchart TB
A["AppModule (ildiz)"] --> B["BogliqliklarModule (@Global)"]
A --> V["VazifalarModule"]
A --> E["EksportModule"]
B -. "ombor, log, sozlamalar" .-> V
B -. "ombor, log" .-> E
V --> VC["VazifalarController, TeglarController"]
V --> VS["VazifalarService (exports)"]
E --> EC["EksportController"]
E --> ES["EksportService"]Diagrammadagi ikki xil chiziqqa qarang. To'liq chiziq — imports va modul ichidagi narsalar. Punktir — @Global moduldan import qilmasdan keladigan provider'lar (ombor, log). Bu daraxt keyingi uch darsda to'liq quriladi; bu darsda modul qutilarining o'zini yasaymiz.
3. Ko'rinish qoidasi — haqiqiy tajriba
3.1 Tajriba sharti
Qoidani so'z bilan aytish oson, tushunish qiyin. Shuning uchun Nest'da tajriba qildik (biz ishga tushirdik: NestJS 12.2.0, Node 24.21.0). Ikki xizmat:
@Injectable()
class SoatService {
hozir(): string {
return '2026-11-01T09:00:00Z';
}
}
@Injectable()
class HisobotService {
constructor(private readonly soat: SoatService) {}
sarlavha(): string {
return `Hisobot (${this.soat.hozir()})`;
}
}@Injectable() — "bu klassni Nest yarata oladi" degan yorliq; keyingi darsdan keyingisida batafsil. HisobotService ga SoatService kerak. Endi ularni turli modullarga joylab, Nest nima deyishini ko'ramiz.
3.2 exports siz
@Module({ providers: [SoatService] })
class SoatYopiqModule {}
@Module({ imports: [SoatYopiqModule], providers: [HisobotService] })
class Hisobot1Module {}Hisobot1Module SoatYopiqModule ni import qildi. Lekin SoatYopiqModule SoatService ni eksport qilmagan. Natija:
Nest can't resolve dependencies of the HisobotService (?). Please make sure that the argument SoatService at index [0] is available in the Hisobot1Module module.
Potential solutions:
- Is Hisobot1Module a valid NestJS module?
- If SoatService is a provider, is it part of the current Hisobot1Module?
- If SoatService is exported from a separate @Module, is that module imported within Hisobot1Module?
@Module({
imports: [ /* the Module containing SoatService */ ]
})
For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errorsTarjimasi: "Nest HisobotService ning bog'liqliklarini topa olmadi (?). Hisobot1Module modulida 0-indeksdagi SoatService argumenti mavjudligiga ishonch hosil qiling."
Xabarni qism-qism o'qing:
HisobotService (?)— qavs ichida constructor argumentlari.?— topilmagani. Ikki argument bo'lsa va ikkinchisi topilmasa —(SoatService, ?).at index [0]— constructor'dagi nechanchi parametr.in the Hisobot1Module module— qaysi modul ichida qidirildi. Bu eng muhim qism: xatoSoatServiceda emas,Hisobot1Modulening ko'rish doirasida.- Uchta maslahat — tekshirish ro'yxati. Bizning holatga uchinchisi yaqin, lekin to'liq emas: modul import qilingan, eksport esa yo'q.
Xato ilova ishga tushayotganda chiqdi, birinchi so'rovda emas. Bu yaxshi: noto'g'ri ulangan ilova umuman ko'tarilmaydi (fail-fast).
3.3 exports bilan — va bitta nusxa
@Module({ providers: [SoatService], exports: [SoatService] })
class SoatModule {}
@Module({ imports: [SoatModule], providers: [HisobotService] })
class Hisobot2Module {}
@Module({ imports: [SoatModule], providers: [EksportService] })
class Eksport2Module {}
@Module({ imports: [Hisobot2Module, Eksport2Module] })
class Ilova2Module {}Endi ikki modul SoatModule ni import qildi. EksportService ham constructor'da SoatService oladi. Tajriba ikkala xizmatdagi SoatService ni === bilan solishtirdi:
2) eksport bilan: OK
Hisobot (2026-11-01T09:00:00Z)
bitta SoatService: truetrue — ikki modul bitta SoatService nusxasini oldi. Modul import qilinganda nusxa ko'chirilmaydi. Butun ilovada SoatModule bitta, uning provider'lari ham bitta. Bunday — ko'p joyda ishlatiladigan — modul shared module (umumiy modul) deyiladi. Nest'da har modul sukut bo'yicha shared: uni qancha modul import qilsa ham, nusxa bitta.
3.4 Tuzoq: ikki joyda providers
Yangi boshlovchi ko'pincha "ko'rinmayaptimi — o'zimning providers ga qo'shaman" deydi:
@Module({ providers: [SoatService, HisobotService] })
class Hisobot5Module {}
@Module({ providers: [SoatService, EksportService] })
class Eksport5Module {}Xato yo'qoladi. Lekin natija:
5) ikki joyda providers: OK
bitta SoatService: falsefalse — endi ilovada ikkita SoatService bor. Har modul o'z providers idagi klassdan o'z nusxasini yaratdi. Soat uchun bu zararsiz tuyuladi. Lekin vazifalar-api dagi EksportService ichida eksport ishlari Map da saqlanadi. Ikki nusxa bo'lsa — bir controller boshlagan ishni ikkinchisi "topilmadi" deydi. Xato jim chiqadi, ishga tushishda hech narsa demaydi.
Diqqat: Provider ko'rinmasa, uni ikkinchi modulning
providersiga ko'chirmang. To'g'ri yo'l: egasidaexports, ishlatuvchidaimports.
3.5 providers da yo'q narsani eksport qilish
@Module({ exports: [SoatService] })
class NotogriModule {}Nest cannot export a provider/module that is not a part of the currently processed module (NotogriModule). Please verify whether the exported SoatService is available in this particular context.Tarjimasi: "Nest joriy modulning (NotogriModule) qismi bo'lmagan provider yoki modulni eksport qila olmaydi." Eksport — o'zingizda bor narsani berish. Yo'q narsani berib bo'lmaydi.
Tekshirib ko'ring:
AmodulBni import qildi,BesaCni import qilib,CServiceni ishlatadi.CCServiceni eksport qilgan.Aichidagi xizmatCServiceni ola oladimi?
Javob
Yo'q. Import o'tkazuvchan emas: A faqat B ning eksportlarini ko'radi. B CService ni o'zi ishlatadi, lekin tashqariga bermagan. A ga kerak bo'lsa — yo A C ni o'zi import qiladi, yo B C ni qayta eksport qiladi (keyingi bo'lim).
4. JS modelida ko'rinish qoidasi
Nest ichida nima bo'layotganini kichik modelda takrorlaymiz. Bu blok brauzerda ishlaydi. Provider — oddiy obyekt: nomi va unga kerak provider'lar ro'yxati. Modul — to'rt maydonli obyekt:
const Soat = { nomi: "SoatService", kerak: [] };
const Hisobot = { nomi: "HisobotService", kerak: [Soat] };
function modul(nomi, sozlama) {
return {
nomi, providers: [], imports: [], exports: [], ...sozlama,
};
}
// Modul ichida ko'rinadi: o'z provider'lari + import qilinganlarning
// eksportlari
function korinadi(m) {
const royxat = new Set(m.providers);
for (const boshqa of m.imports) {
for (const p of boshqa.exports) royxat.add(p);
}
return royxat;
}
function yigish(m) {
for (const p of m.providers) {
p.kerak.forEach((dep, i) => {
if (!korinadi(m).has(dep)) {
throw new Error(`${p.nomi} ning ${i}-argumenti ` +
`(${dep.nomi}) ${m.nomi} da ko'rinmaydi`);
}
});
}
return `${m.nomi}: OK`;
}
const SoatYopiq = modul("SoatYopiq", { providers: [Soat] });
const SoatOchiq = modul("SoatOchiq", {
providers: [Soat],
exports: [Soat],
});
for (const ichki of [SoatYopiq, SoatOchiq]) {
const h = modul(`Hisobot(${ichki.nomi})`, {
imports: [ichki],
providers: [Hisobot],
});
try {
console.log(yigish(h));
} catch (e) {
console.log(e.message);
}
}Konsolda:
HisobotService ning 0-argumenti (SoatService) Hisobot(SoatYopiq) da ko'rinmaydi
Hisobot(SoatOchiq): OKkorinadi funksiyasi — butun qoidaning yuragi. Unda faqat ikki manba bor: modulning o'z providers i va import qilingan modullarning exports i. Import qilingan modulning ichidagi boshqa narsalar bu ro'yxatga tushmaydi. Nest xabari ham aynan shu ikki manbani tekshirishni maslahat bergandi.
Model haqiqiy Nest'dan soddaroq: unda @Global va qayta eksport yo'q. Ularni mashqlarda qo'shasiz.
5. Modul turlari
5.1 Feature modul
Feature modul (xususiyat moduli) — bitta biznes mavzusi: VazifalarModule, EksportModule, keyinroq AuthModule. Ichida o'sha mavzuning controller'lari va xizmatlari. Odatda ko'p narsani eksport qilmaydi — faqat boshqa modullarga haqiqatan kerak bo'lganini.
vazifalar-api da VazifalarModule o'z xizmatini eksport qiladi — boshqa modul (masalan, keyinroq eksport yoki bildirishnomalar) vazifalar mantig'iga muhtoj bo'lsa, VazifalarModule ni import qiladi.
5.2 @Global modul
Ba'zi provider'lar deyarli hamma joyda kerak: log, sozlamalar, ma'lumotlar bazasi ulanishi. Har modulda imports: [LogModule] yozish charchatadi. @Global() dekoratori modulni global qiladi: uning eksportlari hamma modulda import qilmasdan ko'rinadi.
@Global()
@Module({ providers: [SoatService], exports: [SoatService] })
class SoatGlobalModule {}
@Module({ providers: [HisobotService] })
class Hisobot3Module {}
@Module({ imports: [SoatGlobalModule, Hisobot3Module] })
class Ilova3Module {}Hisobot3Module SoatGlobalModule ni import qilmagan. Natija:
3) @Global: OK
Hisobot (2026-11-01T09:00:00Z)Ishladi. Lekin e'tibor bering: global modulni ham bir marta — odatda ildizda — import qilish kerak (Ilova3Module da). Aks holda u daraxtda yo'q.
vazifalar-api da bitta global modul bo'ladi — BogliqliklarModule: ombor, log, xabarchi va sozlamalar. Ular main.ts da, Nest'dan oldin yaratiladi (25-qismdagi omborYarat o'zgarmaydi) va global modul orqali hamma xizmatga beriladi. Qanday berilishi — Custom provider'lar va Dynamic modullar mavzusi.
Diqqat:
@Globalni ko'p ishlatmang. Hammasi global bo'lsa, modul chegarasi yana yo'qoladi — «Nega bu kerak?» bo'limidagi muammoga qaytasiz. Nest hujjati ham shuni ogohlantiradi: global modul — faqat haqiqatan hamma joyda kerak bo'lgan narsa uchun. Qolganidaimportsochiq yozilsin — kim nimaga tayanishi ko'rinib tursin.
5.3 Qayta eksport (re-export)
Modul o'zi import qilgan modulni qayta eksport qila oladi. Bu ko'p kichik modullarni bitta "paket" qilib berish uchun qulay:
@Module({ imports: [SoatModule], exports: [SoatModule] })
class UmumiyModule {}
@Module({ imports: [UmumiyModule], providers: [HisobotService] })
class Hisobot4Module {}4) qayta eksport: OK
Hisobot (2026-11-01T09:00:00Z)Hisobot4Module faqat UmumiyModule ni bildi, lekin SoatService ni oldi. exports ga provider emas, butun modul yozildi — uning hamma eksportlari o'tdi. Real loyihada bu CoreModule yoki SharedModule nomi bilan uchraydi: log, config, baza ulanishi — bitta importda.
5.4 Dinamik modul — bir qarash
Ko'chish tugagan vazifalar-api da AppModule shunday ko'rinadi:
@Module({})
export class AppModule {
static forRoot(b: TashqiBogliqliklar): DynamicModule {
return {
module: AppModule,
imports: [
BogliqliklarModule.forRoot(b),
VazifalarModule,
EksportModule,
],
};
}
}forRoot(...) — statik metod, modulni sozlama bilan qaytaradi. Bu — dinamik modul (dynamic module): modul tarkibi ish vaqtida beriladi. Bu darsda faqat shuni bilish yetadi: @Module({...}) dagi to'rt maydonni metod ham qaytara oladi. Chuqur — Dynamic modullar darsida.
Tekshirib ko'ring: Log xizmati uchun
LogModuleni@Globalqildingiz, lekinAppModuleningimportsiga yozmadingiz. Xizmatlar logni ola oladimi?
Javob
Yo'q. @Global — "eksportlarim hamma joyda ko'rinsin" degani, "men o'zim daraxtga qo'shilaman" degani emas. Daraxtga ulanmagan modulni Nest umuman bilmaydi. Global modul ham bir marta, odatda ildiz modulda, import qilinadi.
6. Modul fayl importi bilan bir narsa emas
Bir chalkashlikni oldindan yechaylik. vazifalar.controller.ts ichida import { VazifalarService } from "./vazifalar.service.ts" yozilgan. Bu ESM import (Nega modullar va ESM export) — TypeScript va Node uchun: "klass qayerda yozilgan". Nest moduli esa boshqa savolga javob beradi: "DI konteyner shu klassdan nusxani kimga bera oladi".
ESM import |
Nest imports |
|
|---|---|---|
| Kim tekshiradi | TypeScript, Node | Nest DI konteyner |
| Qachon | kompilyatsiya, yuklash | NestFactory.create |
| Nima uchun | klassning kodini olish | klassning nusxasini olish |
| Xato | TS2307, ERR_MODULE_NOT_FOUND |
Nest can't resolve dependencies… |
Ikkalasi ham kerak. Klassni ESM bilan import qilib, constructor'ga yozasiz — TypeScript rozi. Lekin Nest modul qoidasi buzilgan bo'lsa, ilova ishga tushmaydi. «Ko'rinish qoidasi» bo'limidagi tajribada ham fayl importlari to'g'ri edi.
7. Ishga tushish logida modullar
Nest logi modullarni ko'rsatadi. «Loyiha qadami» bo'limidagi o'zgarishdan keyin vazifalar-api ni build qilib yurgizdik (biz ishga tushirdik; jarayon raqami va vaqt olib tashlandi):
LOG [NestFactory] Starting Nest application...
LOG [InstanceLoader] VazifalarModule dependencies initialized +8ms
LOG [InstanceLoader] EksportModule dependencies initialized +0ms
LOG [InstanceLoader] AppModule dependencies initialized +0ms
LOG [RoutesResolver] SalomController {/salom}: +7ms
LOG [RouterExplorer] Mapped {/salom, GET} route +3ms
LOG [NestApplication] Nest application successfully started +1ms
vazifalar-api (Nest): http://127.0.0.1:4593Tartibga qarang: avval ichki modullar (VazifalarModule, EksportModule), oxirida ildiz AppModule. Nest daraxtni pastdan yuqoriga yig'adi — xuddi 1-darsdagi JS konteyner bog'liqliklarni pastdan yuqoriga yaratgani kabi. Modul nimaga tayansa, o'sha oldin tayyor bo'ladi.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
Nest can't resolve dependencies of the X (?)… in the YModule |
provider eksport qilinmagan yoki modul import qilinmagan | egasida exports, Y da imports |
| Ma'lumot "yo'qolib qoladi", xato yo'q | provider ikki modulning providers ida — ikki nusxa |
bitta modulda qoldiring, eksport qiling |
Nest cannot export a provider/module that is not a part of… |
exports da providers da yo'q narsa |
avval providers ga yoki imports ga qo'shing |
| Global modul ishlamadi | daraxtga hech qayerda import qilinmagan | ildizda bir marta import |
| Controller marshrutlari yo'q (404) | modul AppModule daraxtiga ulanmagan |
imports ga qo'shing; logda Mapped {…} ni tekshiring |
Jadvaldagi ikkinchi qator eng xavflisi. Birinchi va uchinchi xato ilovani ishga tushirmaydi — siz uni darrov ko'rasiz. Ikki nusxa esa ishlab turgan ilovada sekin "o'zini ko'rsatadi": hisoblagich ikkiga bo'linadi, kesh yarim ishlaydi, eksport ishi "topilmadi" bo'ladi. Shunday g'alati xatoni ko'rsangiz — avval provider qaysi modullarning providers ida turganini qidiring.
Oxirgisi eng jim xato: ilova ko'tariladi, lekin marshrut yo'q. Logdagi RoutesResolver va Mapped qatorlari — birinchi tekshiruv joyi.
9. Mashqlar
Mashqlar kurs/mashqlar/30/03-modullar/ da.
1-mashq (oson): ko'rinadimi?
SmsModule SmsService ni providers ga yozgan, exports ga yozmagan. BildirishnomaModule SmsModule ni import qilgan. To'ldiring:
BildirishnomaServiceSmsServiceni ola oladimi? —- Xabarda qaysi modul nomi turadi? —
- Tuzatish uchun qaysi modulning qaysi maydoniga yozish kerak?
SmsModulening SmsServiceniBildirishnomaModuleningprovidersiga ham yozsak, ilovada nechtaSmsServicebo'ladi? —
Yechim
- yo'q — import bor, eksport yo'q.
- BildirishnomaModule — Nest bog'liqlikni ishlatuvchi modul ichida qidiradi:
…is available in the BildirishnomaModule module. - exports —
exports: [SmsService]. - 2 — har
providerso'z nusxasini yaratadi; xato yo'qoladi, lekin SMS hisoblagichi kabi holat ikkiga bo'linadi.
2-mashq (o'rta): modelga @Global qo'shing
Darsdagi JS modeliga global: true sozlamasini qo'shing. korinadi(m, globallar) endi ikkinchi argument oladi: global modullar ro'yxati, ularning eksportlari ham ko'rinadi. yigish(m, globallar) ham uni uzatsin. Sinov: SoatGlobal (global, Soat ni eksport qiladi) va Hisobot moduli (hech narsa import qilmaydi). Ishora: for (const boshqa of [...m.imports, ...globallar]) (spread).
Yechim
const Soat = { nomi: "SoatService", kerak: [] };
const Hisobot = { nomi: "HisobotService", kerak: [Soat] };
function modul(nomi, sozlama) {
return {
nomi, providers: [], imports: [], exports: [], global: false,
...sozlama,
};
}
function korinadi(m, globallar) {
const royxat = new Set(m.providers);
for (const boshqa of [...m.imports, ...globallar]) {
for (const p of boshqa.exports) royxat.add(p);
}
return royxat;
}
function yigish(m, globallar = []) {
for (const p of m.providers) {
p.kerak.forEach((dep, i) => {
if (!korinadi(m, globallar).has(dep)) {
throw new Error(`${p.nomi} ning ${i}-argumenti ` +
`(${dep.nomi}) ${m.nomi} da ko'rinmaydi`);
}
});
}
return `${m.nomi}: OK`;
}
const SoatGlobal = modul("SoatGlobal", {
providers: [Soat], exports: [Soat], global: true,
});
const H = modul("Hisobot", { providers: [Hisobot] });
const hamma = [SoatGlobal, H];
const globallar = hamma.filter((m) => m.global);
for (const g of [[], globallar]) {
try {
console.log(yigish(H, g));
} catch (e) {
console.log(e.message);
}
}Konsolda:
HisobotService ning 0-argumenti (SoatService) Hisobot da ko'rinmaydi
Hisobot: OKBirinchi yugurishda global ro'yxat bo'sh — "daraxtga ulanmagan global modul" holati. Ikkinchisida SoatGlobal daraxtda va global — Hisobot import qilmasdan oldi. hamma massivi — ilova daraxtidagi modullar; Nest ham global modullarni faqat daraxtdan topadi.
3-mashq (qiyin): modul tekshiruvchisi
tekshirModul(m) funksiyasini yozing. U ikki xil xatoni topib, satrlar massivini qaytarsin (xato bo'lmasa — bo'sh massiv):
exportsdagi provider naprovidersda, na import qilingan modulning eksportida yo'q →"<modul>: <provider> eksport qilingan, lekin modulda yo'q".- Provider bir nechta modulning
providersida uchraydi →"<provider> ikki marta yaratiladi: <modul1>, <modul2>". Buni butun ro'yxat uchun tekshiradigantakrorlar(modullar)funksiyasi qilsin.
Ishora: Map da provider → modul nomlari ro'yxatini yig'ing (Map).
Yechim
const Soat = { nomi: "SoatService" };
const Sms = { nomi: "SmsService" };
function modul(nomi, sozlama) {
return {
nomi, providers: [], imports: [], exports: [], ...sozlama,
};
}
function tekshirModul(m) {
const bor = new Set(m.providers);
for (const boshqa of m.imports) {
for (const p of boshqa.exports) bor.add(p);
}
return m.exports
.filter((p) => !bor.has(p))
.map((p) => `${m.nomi}: ${p.nomi} eksport qilingan, ` +
"lekin modulda yo'q");
}
function takrorlar(modullar) {
const qayerda = new Map();
for (const m of modullar) {
for (const p of m.providers) {
qayerda.set(p, [...(qayerda.get(p) ?? []), m.nomi]);
}
}
return [...qayerda]
.filter(([, nomlar]) => nomlar.length > 1)
.map(([p, nomlar]) =>
`${p.nomi} ikki marta yaratiladi: ${nomlar.join(", ")}`);
}
const SoatM = modul("SoatModule", {
providers: [Soat], exports: [Soat],
});
const Notogri = modul("NotogriModule", { exports: [Sms] });
const Hisobot = modul("HisobotModule", { providers: [Soat] });
const Qayta = modul("UmumiyModule", {
imports: [SoatM], exports: [Soat],
});
const hamma = [SoatM, Notogri, Hisobot, Qayta];
for (const m of hamma) {
for (const x of tekshirModul(m)) console.log(x);
}
for (const x of takrorlar(hamma)) console.log(x);Konsolda:
NotogriModule: SmsService eksport qilingan, lekin modulda yo'q
SoatService ikki marta yaratiladi: SoatModule, HisobotModuleUmumiyModule xato bermadi: u Soat ni o'zi yaratmaydi, import qilgan modulning eksportidan qayta beradi. Birinchi xato Nest'ning Nest cannot export a provider/module… xatosiga mos — Nest uni ishga tushishda o'zi beradi. Ikkinchisini esa Nest bermaydi — u jim ikki nusxa yaratadi. Shunday tekshiruvni katta loyihada test sifatida yozish mumkin: Nest'ning DiscoveryService modullar ro'yxatini beradi (Reflector va DiscoveryService).
10. Loyiha qadami: modul qutilari
Bu va keyingi uch dars bitta katta qadamning qismlari: butun v1 API Nest'ga o'tadi. Har darsda bitta qismni qo'shamiz, commit esa Bootstrap: main.ts darsida bitta bo'ladi. Bu darsda — modul fayllari. Ichini keyingi darslar to'ldiradi.
src/vazifalar/vazifalar.module.ts:
// vazifalar.module.ts — vazifalar xususiyat moduli:
// controller'lar + xizmat
import { Module } from "@nestjs/common";
@Module({
// controllers — keyingi darsda, providers va exports — undan keyin
})
export class VazifalarModule {}src/eksport/eksport.module.ts:
// eksport.module.ts — eksport xususiyat moduli
import { Module } from "@nestjs/common";
@Module({})
export class EksportModule {}src/app.module.ts — ikkala modul daraxtga ulanadi:
// app.module.ts — ildiz modul: ilova shu moduldan boshlab
// yig'iladi (imports daraxti)
import { Module } from "@nestjs/common";
import { SalomController } from "./salom.controller.ts";
import { VazifalarModule } from "./vazifalar/vazifalar.module.ts";
import { EksportModule } from "./eksport/eksport.module.ts";
@Module({
imports: [VazifalarModule, EksportModule],
controllers: [SalomController],
})
export class AppModule {}Fayl nomlari Nest uslubida (*.module.ts), mavzu so'zi o'zbekcha. Eski vazifalar/marshrut.ts, xizmat.ts va eksport/eksport.ts hali joyida — Express API ular bilan ishlashda davom etadi.
Tekshiruv:
npm run tip
npm run lint
npm test
npm run build
npm startBiz kanon nusxasida shu o'zgarish bilan yurgizdik: tip 0 xato, lint 0, Vitest 2/2, build o'tdi, ishga tushish logi — «Ishga tushish logida modullar» bo'limidagi. GET /salom hali {"xabar":"Salom, Nest!"} qaytaradi.
Ko'chish tugagach bu fayllarning yakuniy ko'rinishi (kanon): VazifalarModule — controllers: [VazifalarController, TeglarController], providers: [VazifalarService], exports: [VazifalarService]; EksportModule — EksportController va EksportService; AppModule — forRoot bilan, «Dinamik modul — bir qarash» bo'limidagi ko'rinishda. Hali commit qilmang.
11. Real ishda
- Katta loyihalarda modullar soni o'nlab:
AuthModule,UsersModule,PaymentsModule,NotificationsModule. Yangi dasturchiapp.module.tsni ochib, butun tizim xaritasini ko'radi. - Kod review'da eng ko'p savol: "bu provider nega ikki modulning
providersida?" va "nega bu modul@Global?". - Modular monolit — modullar chegarasini qat'iy saqlab, keyinchalik ularni alohida xizmatga ajratish mumkin bo'lgan arxitektura. Nest modullari bunga tayyor asos (Modular monolit va hexagonal arxitektura).
- Intervyu: "Nest'da provider boshqa modulda qanday ishlatiladi?", "
@Globalqachon kerak va nega kam ishlatish kerak?", "Shared module nima?".
Xulosa
@Module— to'rt maydon:controllers,providers,imports,exports; klassning o'zi bo'sh tashuvchi.- Provider sukut bo'yicha faqat o'z modulida; boshqa modulga — egasida
exports, ishlatuvchidaimports. - Import o'tkazuvchan emas; qayta eksport bilan bir nechta modulni bitta qilib berish mumkin.
- Modul import qilinganda nusxa ko'chmaydi — shared; ikki
providersesa jim ikki nusxa beradi. @Global— import qilmasdan ko'rinadi, lekin daraxtga bir marta ulanadi; kam ishlating.- ESM
import— klass kodi uchun, Nestimports— klass nusxasi uchun.
Keyingi dars: Controller'lar va route dekoratorlari — vazifalar-api ning marshrutlarini @Controller, @Get, @Param, @Body bilan yozamiz va @Res() tuzog'ini ko'ramiz.
Manbalar
- NestJS hujjati — Modules (shared, global, re-export, dynamic): https://docs.nestjs.com/modules
- NestJS hujjati — Common errors ("Cannot resolve dependency"): https://docs.nestjs.com/faq/common-errors
- Kanon (IlmHamroh, 2026-10-27):
vazifalar-apimodul tuzilmasi, NestJS 12.2.0. Modul tajribalari (eksportsiz, eksport,@Global, qayta eksport, ikkiproviders, noto'g'ri eksport) vavazifalar-apiishga tushish logi — biz ishga tushirdik (2026-11-01, NestJS 12.2.0, Node 24.21.0).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!