Lazy Loading
Lazy loading — modul yoki component faqat foydalanuvchi route'ga o'tganda yuklanadi. Boshlang'ich bundle hajmi kamayadi, ilova tezroq ochiladi.
loadChildren — lazy module
Nima bu?
loadChildren — route config'da dynamic import bilan NgModule yuklash. Webpack/Vite alohida chunk yaratadi. Foydalanuvchi /admin ga o'tganda AdminModule yuklanadi.
DI scoping gotcha: har bir lazy yuklangan modul o'zining alohida child injectorini yaratadi. Agar service allaqachon providedIn: 'root' bo'lsa-yu, lazy modul uni yana o'z providers massivida ham ro'yxatdan o'tkazsa — natijada ikkita alohida instance paydo bo'ladi: root injector'dagi singleton va lazy subtree uchun yaratilgan yangi instance. Lazy modul ichidagi component'lar shu ikkinchi (boshqa) instance'ni oladi, root/boshqa feature'dagi component'lar esa birinchisini — natijada ikkalasi ham "singleton" deb o'ylangan holda state sinxron bo'lmay qoladi. Yechim: service faqat providedIn: 'root' orqali e'lon qilinsin, lazy modul providers'ida qayta ko'rsatilmasin.
Kod misoli
// app.routes.ts
export const routes: Routes = [
{ path: '', component: HomeComponent },
{
path: 'admin',
loadChildren: () =>
import('./admin/admin.module').then((m) => m.AdminModule),
},
{
path: 'reports',
loadChildren: () =>
import('./reports/reports.module').then((m) => m.ReportsModule),
},
];
// admin/admin.module.ts
@NgModule({
declarations: [AdminDashboardComponent, UserManageComponent],
imports: [
CommonModule,
RouterModule.forChild([
{ path: '', component: AdminDashboardComponent },
{ path: 'users', component: UserManageComponent },
]),
],
})
export class AdminModule {}
Imtihonda
Savol: Lazy modul AppModule imports da bo'lishi kerakmi?
Javob: Yo'q. Lazy modul faqat loadChildren orqali yuklanadi. AppModule'ga import qilinsa eager bo'ladi — lazy ma'nosi yo'qoladi.
Savol: Lazy modul providers'idagi AuthService root'dagi AuthService bilan bir xil instance bo'ladimi?
Javob: Faqat providedIn: 'root' bo'lsa — ha. Agar service lazy modulning o'z providers massivida qayta ro'yxatdan o'tgan bo'lsa — yo'q, chunki lazy modul alohida child injector yaratadi va shu subtree uchun yangi instance quriladi.
Yodlash uchun
loadComponent — standalone lazy (v14+)
Nima bu?
Angular 14+ da butun NgModule'siz bitta standalone component lazy yuklash mumkin. Kichik route'lar uchun modul yaratish shart emas — to'g'ridan-to'g'ri component import qilinadi.
Kod misoli
// app.routes.ts
export const routes: Routes = [
{
path: 'settings',
loadComponent: () =>
import('./settings/settings.component').then((m) => m.SettingsComponent),
},
{
path: 'profile',
loadComponent: () =>
import('./profile/profile.component').then((m) => m.ProfileComponent),
},
];
// settings/settings.component.ts
@Component({
selector: 'app-settings',
standalone: true,
imports: [ReactiveFormsModule, RouterLink],
template: `<h1>Sozlamalar</h1>`,
})
export class SettingsComponent {}
Imtihonda
Savol: loadChildren vs loadComponent — qachon qaysi biri?
Javob: loadComponent — bitta standalone page, modul kerak emas. loadChildren — ko'p component/directive/pipe bor feature modul yoki legacy NgModule arxitektura.
Yodlash uchun
RouterModule.forRoot vs forChild
Nima bu?
forRoot(routes)— root AppModule (yokiprovideRouter) da. Router service singleton yaratadi. Faqat bir marta chaqiriladi.forChild(routes)— feature/lazy modulda. Mavjud router'ga route qo'shadi, yangi router instance yaratmaydi.
Kod misoli
// app-routing.module.ts — ROOT
@NgModule({
imports: [RouterModule.forRoot(routes, {
enableTracing: false,
scrollPositionRestoration: 'enabled',
})],
exports: [RouterModule],
})
export class AppRoutingModule {}
// products/products-routing.module.ts — CHILD
const routes: Routes = [
{ path: '', component: ProductListComponent },
{ path: ':id', component: ProductDetailComponent },
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ProductsRoutingModule {}
// Standalone ekvivalenti
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes, withComponentInputBinding()),
],
});
Imtihonda
Savol: Feature modulda forRoot ishlatilsa nima bo'ladi?
Javob: Xato yoki noaniq xatti-harakat — ikkinchi router instance, route'lar ishlamasligi. Feature modulda doim forChild.
Yodlash uchun
Preloading — PreloadAllModules, custom strategy
Nima bu?
Preloading — lazy modullarni foydalanuvchi route'ga o'tishidan oldin (bo'sh vaqtda) fon rejimida yuklash. PreloadAllModules — barcha lazy modullarni yuklaydi. Custom strategy — faqat muhim modullarni (masalan, admin emas, dashboard ha).
Kod misoli
import {
PreloadAllModules,
PreloadingStrategy,
Route,
} from '@angular/router';
import { Observable, of, timer } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
// Barcha lazy modullarni preload
RouterModule.forRoot(routes, {
preloadingStrategy: PreloadAllModules,
})
// Custom strategy
@Injectable({ providedIn: 'root' })
export class SelectivePreloadStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<unknown>): Observable<unknown> {
if (route.data?.['preload']) {
return timer(2000).pipe(mergeMap(() => load())); // 2s kutib yukla
}
return of(null);
}
}
// Route config
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule),
data: { preload: true },
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
data: { preload: false }, // faqat kerak bo'lganda
}
// Standalone
provideRouter(routes, withPreloading(SelectivePreloadStrategy))
Imtihonda
Savol: PreloadAllModules qachon foydali, qachon zarar?
Javob: Foydali — kam lazy modul, tez navigation kerak. Zarar — ko'p/katta modul, mobil tarmoq — boshlang'ich trafik ortadi.
Yodlash uchun
Webpack Bundle Analyzer — bundle ko'rish
Nima bu?
Bundle analyzer — build natijasidagi JS fayllar hajmini vizual ko'rsatadi. Qaysi modul/kutubxona ko'p joy egallaganini aniqlash, lazy loading samarasini tekshirish uchun. Angular CLI: ng build --stats-json + webpack-bundle-analyzer.
Kod misoli
# Stats fayl yaratish
ng build --configuration=production --stats-json
# Analyzer ishga tushirish
npx webpack-bundle-analyzer dist/my-app/stats.json
// package.json scripts
{
"scripts": {
"analyze": "ng build --configuration=production --stats-json && webpack-bundle-analyzer dist/my-app/stats.json"
}
}
// Lazy loading samarasini tekshirish — alohida chunk bo'lishi kerak
// stats.json da ko'rinadi:
// - main.js (kichik)
// - admin-admin-module.js (lazy chunk)
// - products-products-module.js (lazy chunk)
// Muammo: moment.js butun main bundle'da 300KB
// Yechim: date-fns tree-shake yoki lazy import
Imtihonda
Savol: Lazy modul qanday tekshiriladi — to'g'ri ishlayaptimi?
Javob: Production build + stats analyzer. Lazy modul alohida chunk (.js fayl) sifatida ko'rinishi kerak. Agar main bundle'da bo'lsa — eager import xato bor.
Yodlash uchun
