Angular懒加载路由下组件未按预期顺序加载问题求助
Angular懒加载路由子模块先于父组件加载问题修复方案
问题根因
- Angular默认路由加载逻辑为:先完整匹配当前URL对应的所有层级懒加载模块,全部加载完成后才会从父到子渲染组件树。访问
/dashboard路径时,TopModule和DashboardModule会并行加载,若DashboardModule体积更大,就会先完成TopModule加载、再完成DashboardModule加载,最后才渲染TopComponent,出现加载顺序异常。 - 现有代码存在错误配置:TopModule重复导入了仅能在根模块引入的
BrowserModule、BrowserAnimationsModule,既会拉长模块加载耗时,也可能引发依赖实例异常,加剧页面卡顿。
修复方案
第一步:修正模块导入错误
删除TopModule中多余的模块导入,仅保留必要依赖:
// top.module.ts 修正后的imports部分 @NgModule({ declarations: [TopComponent], imports: [ CommonModule, // 删除BrowserModule、BrowserAnimationsModule,这两个仅需在AppModule导入 RouterModule.forChild(appRoutes) ] }) export class TopModule {}
第二步:调整路由加载顺序,保证父组件优先渲染
通过路由守卫控制子模块加载时机,等TopComponent初始化完成后再加载子模块:
- 新增状态服务存储TopComponent初始化状态
// top-state.service.ts import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class TopStateService { isTopComponentInit = new BehaviorSubject<boolean>(false); }
- 新增canLoad守卫控制子模块加载时机
// top-load.guard.ts import { Injectable } from '@angular/core'; import { CanLoad, Route, UrlSegment } from '@angular/router'; import { Observable } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { TopStateService } from './top-state.service'; @Injectable({ providedIn: 'root' }) export class TopLoadGuard implements CanLoad { constructor(private topState: TopStateService) {} canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> { return this.topState.isTopComponentInit.pipe( filter(isInit => isInit), take(1) ); } }
- TopComponent初始化时更新状态
// top.component.ts import { Component, OnInit } from '@angular/core'; import { TopStateService } from './top-state.service'; @Component({ selector: 'app-top', templateUrl: './top.component.html' }) export class TopComponent implements OnInit { constructor(private topState: TopStateService) {} ngOnInit(): void { this.topState.isTopComponentInit.next(true); } }
- 给子路由加上守卫配置
// top.module.ts 修正后的路由配置 const appRoutes: Routes = [ { path: '', component: TopComponent, children: [ { path: '', loadChildren: './first.module#FirstModule', canLoad: [TopLoadGuard] }, { path: 'dashboard', loadChildren: './dashboard.module#DashboardModule', canLoad: [TopLoadGuard] }, ] } ]
可选优化
如果不想新增守卫,也可以对DashboardModule做体积优化:开启生产环境treeshaking、拆分子模块、按需引入第三方依赖,减少模块加载耗时,降低对TopComponent渲染的阻塞影响。
内容的提问来源于stack exchange,提问作者Nitin
相关产品推荐
相关产品推荐

