模块与懒加载 #

一、模块概述 #

Angular模块(NgModule)用于组织应用结构,管理组件、指令、管道和服务。

二、NgModule #

2.1 模块结构 #

typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';

import { UserListComponent } from './user-list.component';
import { UserDetailComponent } from './user-detail.component';
import { UserService } from './user.service';

@NgModule({
  declarations: [
    UserListComponent,
    UserDetailComponent
  ],
  imports: [
    CommonModule,
    FormsModule,
    RouterModule
  ],
  exports: [
    UserListComponent
  ],
  providers: [
    UserService
  ]
})
export class UserModule { }

2.2 模块配置项 #

配置项 说明
declarations 声明组件、指令、管道
imports 导入其他模块
exports 导出供其他模块使用
providers 注册服务
bootstrap 根组件

2.3 常用模块 #

模块 说明
BrowserModule 浏览器支持
CommonModule 通用指令和管道
FormsModule 模板驱动表单
ReactiveFormsModule 响应式表单
HttpClientModule HTTP客户端
RouterModule 路由

三、独立组件 #

3.1 独立组件(Standalone) #

typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-user-card',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div class="card">
      <h3>{{ user.name }}</h3>
      <input [(ngModel)]="user.email" />
    </div>
  `
})
export class UserCardComponent {
  user = { name: 'John', email: 'john@example.com' };
}

3.2 引导独立应用 #

typescript
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';

bootstrapApplication(AppComponent, appConfig)
  .catch(err => console.error(err));

3.3 应用配置 #

typescript
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient()
  ]
};

四、懒加载 #

4.1 路由懒加载模块 #

typescript
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'users',
    loadChildren: () => import('./users/users.module')
      .then(m => m.UsersModule)
  },
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.module')
      .then(m => m.AdminModule)
  }
];

4.2 懒加载模块路由 #

typescript
@NgModule({
  imports: [
    RouterModule.forChild([
      { path: '', component: UserListComponent },
      { path: ':id', component: UserDetailComponent }
    ])
  ],
  declarations: [UserListComponent, UserDetailComponent]
})
export class UsersModule { }

4.3 懒加载独立组件 #

typescript
export const routes: Routes = [
  {
    path: 'users',
    loadComponent: () => import('./users/user-list.component')
      .then(c => c.UserListComponent)
  },
  {
    path: 'users/:id',
    loadComponent: () => import('./users/user-detail.component')
      .then(c => c.UserDetailComponent)
  }
];

五、预加载策略 #

5.1 预加载所有模块 #

typescript
import { provideRouter, PreloadAllModules } from '@angular/router';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes, PreloadAllModules)
  ]
};

5.2 自定义预加载策略 #

typescript
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class SelectivePreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, load: () => Observable<any>): Observable<any> {
    if (route.data?.['preload']) {
      return load();
    }
    return of(null);
  }
}

// 配置路由
export const routes: Routes = [
  {
    path: 'users',
    loadChildren: () => import('./users/users.module').then(m => m.UsersModule),
    data: { preload: true }
  },
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
    data: { preload: false }
  }
];

// 应用配置
export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes, SelectivePreloadingStrategy)
  ]
};

5.3 按需预加载 #

typescript
@Injectable({ providedIn: 'root' })
export class OnDemandPreloadService {
  private preloadSubject = new Subject<string>();
  preload$ = this.preloadSubject.asObservable();
  
  startPreload(modulePath: string) {
    this.preloadSubject.next(modulePath);
  }
}

@Injectable({ providedIn: 'root' })
export class OnDemandPreloadingStrategy implements PreloadingStrategy {
  constructor(private preloadService: OnDemandPreloadService) {}
  
  preload(route: Route, load: () => Observable<any>): Observable<any> {
    return this.preloadService.preload$.pipe(
      filter(path => path === route.path),
      first(),
      switchMap(() => load())
    );
  }
}

六、模块组织 #

6.1 功能模块 #

text
src/app/
├── core/                      # 核心模块
│   ├── services/
│   ├── guards/
│   ├── interceptors/
│   └── core.module.ts
├── shared/                    # 共享模块
│   ├── components/
│   ├── directives/
│   ├── pipes/
│   └── shared.module.ts
├── features/                  # 功能模块
│   ├── user/
│   │   ├── components/
│   │   ├── services/
│   │   └── user.module.ts
│   └── product/
│       ├── components/
│       ├── services/
│       └── product.module.ts
└── app.module.ts

6.2 核心模块 #

typescript
@NgModule({
  imports: [CommonModule, HttpClientModule],
  providers: [
    AuthService,
    ApiService,
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ]
})
export class CoreModule {
  constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error('CoreModule只能被AppModule导入');
    }
  }
}

6.3 共享模块 #

typescript
@NgModule({
  imports: [CommonModule, FormsModule, ReactiveFormsModule],
  declarations: [
    ButtonComponent,
    InputComponent,
    HighlightDirective,
    TruncatePipe
  ],
  exports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    ButtonComponent,
    InputComponent,
    HighlightDirective,
    TruncatePipe
  ]
})
export class SharedModule { }

七、模块最佳实践 #

7.1 模块划分原则 #

  • 核心模块:全局服务、单例服务
  • 共享模块:可复用组件、指令、管道
  • 功能模块:按业务功能划分

7.2 避免循环依赖 #

typescript
// 错误:模块A导入模块B,模块B导入模块A
// 正确:提取共享部分到共享模块

7.3 服务作用域 #

typescript
// 全局单例
@Injectable({ providedIn: 'root' })

// 模块级单例
@NgModule({
  providers: [FeatureService]
})

// 组件级实例
@Component({
  providers: [ComponentService]
})

八、性能优化 #

8.1 懒加载策略 #

typescript
// 按需加载
{
  path: 'feature',
  loadChildren: () => import('./feature/feature.module')
    .then(m => m.FeatureModule)
}

8.2 预加载关键模块 #

typescript
{
  path: 'dashboard',
  loadChildren: () => import('./dashboard/dashboard.module')
    .then(m => m.DashboardModule),
  data: { preload: true }
}

8.3 减少模块大小 #

typescript
// 按需导入
import { CommonModule } from '@angular/common';

// 避免导入整个模块
// import { CommonModule } from '@angular/common';
// 改为只导入需要的

九、总结 #

概念 说明
NgModule 模块定义
declarations 声明组件、指令、管道
imports 导入模块
exports 导出模块内容
providers 注册服务
懒加载 按需加载模块
预加载 提前加载模块
独立组件 无需模块的组件

下一步:Angular样式指南

最后更新:2026-03-26