Module arxitekturasi
Katta Angular ilovalar modul arxitekturasi bilan tashkil etiladi: Core (singleton), Shared (qayta ishlatiladigan UI), Feature (biznes funksionallik).
Feature module — bitta funksionallik
Nima bu?
Feature module — ilovaning bitta funksional bo'limi: Products, Orders, Admin. O'z component, service va route'larini o'z ichiga oladi. Lazy loading uchun ideal — faqat kerak bo'lganda yuklanadi. RouterModule.forChild() ishlatiladi.
Kod misoli
// products/products.module.ts
@NgModule({
declarations: [
ProductListComponent,
ProductDetailComponent,
ProductFilterComponent,
],
imports: [
CommonModule,
SharedModule,
ReactiveFormsModule,
RouterModule.forChild([
{ path: '', component: ProductListComponent },
{ path: ':id', component: ProductDetailComponent },
]),
],
providers: [ProductService],
})
export class ProductsModule {}
// app-routing.module.ts
const routes: Routes = [
{
path: 'products',
loadChildren: () =>
import('./products/products.module').then((m) => m.ProductsModule),
},
];
Imtihonda
Savol: Feature module AppModule'ga to'g'ridan-to'g'ri import qilinsa lazy bo'ladimi?
Javob: Yo'q. loadChildren ishlatilmasa, modul eager yuklanadi — boshlang'ich bundle'ga kiradi.
Yodlash uchun
SharedModule — umumiy component/pipe/directive
Nima bu?
SharedModule — ko'p feature modullar ishlatadigan UI elementlar: Button, Modal, Pipe, Directive. declarations + exports bir xil to'plam. Kerakli Angular modullarni ham import qilib, re-export qiladi — feature modul faqat SharedModule import qilsa yetadi.
Kod misoli
@NgModule({
declarations: [
LoadingSpinnerComponent,
ConfirmDialogComponent,
TruncatePipe,
AutofocusDirective,
],
imports: [
CommonModule,
ReactiveFormsModule,
],
exports: [
// O'z component'lar
LoadingSpinnerComponent,
ConfirmDialogComponent,
TruncatePipe,
AutofocusDirective,
// Re-export — feature modul alohida import qilmasin
CommonModule,
ReactiveFormsModule,
],
})
export class SharedModule {}
// Feature modul — minimal import
@NgModule({
declarations: [OrderListComponent],
imports: [SharedModule, RouterModule.forChild([...])],
})
export class OrdersModule {}
Imtihonda
Savol: SharedModule'da service provider qo'yish to'g'rimi?
Javob: Ehtiyotkorlik. SharedModule ko'p joyda import qilinadi — service har import'da yangi instance bo'lishi mumkin (providedIn bo'lmasa). Singleton service → CoreModule yoki providedIn: 'root'.
Yodlash uchun
CoreModule — singleton service'lar
Nima bu?
CoreModule — ilova bo'ylab bitta instance bo'lishi kerak service'lar: AuthService, ApiService, ErrorHandler. Faqat AppModule (root) da import qilinadi. Header, Footer kabi singleton component'lar ham shu yerda bo'lishi mumkin.
Kod misoli
@NgModule({
imports: [CommonModule, HttpClientModule],
providers: [
AuthService,
ApiService,
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
],
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parent: CoreModule) {
if (parent) {
throw new Error('CoreModule faqat AppModule da import qilinadi');
}
}
}
// app.module.ts
@NgModule({
imports: [
BrowserModule,
CoreModule, // bir marta
SharedModule,
AppRoutingModule,
],
bootstrap: [AppComponent],
})
export class AppModule {}
Imtihonda
Savol: Zamonaviy Angular'da CoreModule kerakmi?
Javob: Kamroq. providedIn: 'root' va bootstrapApplication + providers ko'p holatda CoreModule o'rnini bosadi. Legacy loyihalarda hali muhim pattern.
Yodlash uchun
CoreModule guard — @SkipSelf ikki marta import oldini olish
Nima bu?
CoreModule constructor'ida @Optional() @SkipSelf() inject qilinadi. Agar CoreModule allaqachon yuqori injector'da bo'lsa (ikkinchi marta import), xato tashlanadi. Bu singleton service'lar ikki marta yaratilishining oldini oladi.
Kod misoli
import { NgModule, Optional, SkipSelf } from '@angular/core';
@NgModule({
providers: [AuthService, LoggerService],
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error(
'CoreModule allaqachon yuklangan. ' +
'Faqat AppModule (yoki root config) da import qiling.'
);
}
}
}
// XATO — feature modulda CoreModule import
@NgModule({
imports: [CoreModule], // Runtime error!
})
export class ProductsModule {}
// Standalone ekvivalenti — faqat main.ts da providers
bootstrapApplication(AppComponent, {
providers: [
AuthService, // providedIn: 'root' yaxshiroq
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
],
});
Imtihonda
Savol: @SkipSelf nima qiladi bu yerda?
Javob: Joriy injector'dagi CoreModule'ni o'tkazib, ota injectordan qidiradi. Topilsa — ikkinchi import, xato tashlanadi.
Yodlash uchun
