- 异步路由的预加载示例: 为了尽可能减小初始加载体积和最快的加载速度,让 主模块和A模块 先加载;如何懒加载其他模块,但是B 模块可能是 用户在打开应用后,几分钟或几秒钟就会访问的模块;(比如打开微信后,是不是进入主页面;然后是不是要打开朋友圈瞅瞅;而B模块就相当于朋友圈功能;)所以,这个时候在用户打开B模块前;该模块就已经预加载完毕可供访问;
- 预加载原理:
- 每次成功导航后,路由器会在自己的配置中查找尚未加载并且可以预加载的模块
- 预加载策略:
- 默认 都不预加载,懒加载的模块仍会按需加载
- 预加载所有懒加载模块
- 自定义预加载
- 用户场景:将CrisisCenterModule 改为默认懒加载,并使用全部预加载策略来加载所有懒加载模块
- 对crisis-center 模块进行懒加载处理
// crisis-center-routing.ts 该路径为空路径
const crisisCenterRoutes: Routes = [
{
path: '', component: CrisisCenterComponent, children: [
{ path: '', component: CrisisListComponent, children: [
// tslint:disable-next-line: max-line-length
{ path: ':id', component: CrisisDetailComponent, canDeactivate: [CanDeactivateGuard], resolve: { crisis: CrisisDetailResolverService }},
{ path: '', component: CrisisCenterHomeComponent}
]}
]
}
];
// AppRoutingModule 增加该模块路由,并设置loadChildren
const appRoutes: Routes = [
{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule),
canLoad: [AuthGuard]
},
{
path: 'crisis-center',
loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule),
data: { preload: true } // 自定义预加载
},
{ path: '', redirectTo: '/superheroes', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
// AppModule 中 移除该模块
import { HeroesModule } from './heroes/heroes.module';
// import { CrisisCenterModule } from './crisis-center/crisis-center.module';
// import { AdminModule} from './admin/admin.module';
import { AuthModule} from './auth/auth.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; // 导入动画模块
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { ComposeMessageComponent } from './compose-message/compose-message.component';
@NgModule({
declarations: [
AppComponent,
PageNotFoundComponent,
ComposeMessageComponent
],
imports: [
BrowserModule,
FormsModule,
HeroesModule,
// CrisisCenterModule,
// AdminModule,
AuthModule,
AppRoutingModule,
BrowserAnimationsModule
],
- 为所有懒加载模块启动预加载功能,在AppRoutingModule 中导入PreloadAllModules
import { NgModule } from '@angular/core';
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';
import { ComposeMessageComponent } from './compose-message/compose-message.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { AuthGuard } from './auth/auth.guard';
const appRoutes: Routes = [
{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule),
canLoad: [AuthGuard] //CanLoad 会阻塞预加载,该优先级高于预加载策略
},
{
path: 'crisis-center',
loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule),
data: { preload: true }
},
{ path: '', redirectTo: '/superheroes', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{
enableTracing: false,
preloadingStrategy: PreloadAllModules, //让所有(带loadChildren属性的路由)懒加载模块立即预加载
}
)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
- 关于自定义预加载;这里自定义策略为:只预加载data.preload 为 true 的路由;
- 生成自定义服务
ng generate service selective-preloading-strategy
import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class SelectivePreloadingStrategyService implements PreloadingStrategy {
preloadedModules: string[] = [];
// 参数 route -- 要加载的路由 load() -- 加载器函数,异步加载带路由的模块
// 如果该路由应该预加载,就会跳用load()函数返回Observable对象,否则返回null;
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data && route.data['preload']) {
this.preloadedModules.push(route.path); //会将所选路由记录在数组中;
console.log('Preloaded: ' + route.path);
return load();
} else {
return of(null);
}
}
}
- 自定义预加载处理
// AppRoutingModule
import { NgModule } from '@angular/core';
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';
import { ComposeMessageComponent } from './compose-message/compose-message.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { AuthGuard } from './auth/auth.guard';
import { SelectivePreloadingStrategyService } from './selective-preloading-strategy.service';
const appRoutes: Routes = [
{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule),
canLoad: [AuthGuard]
},
{
path: 'crisis-center',
loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule),
data: { preload: true }
},
{ path: '', redirectTo: '/superheroes', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{
enableTracing: false,
preloadingStrategy: SelectivePreloadingStrategyService,
}
)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
- 编辑adminDashboardComponent 来显示预加载路由日志, 当加载完初始路由后,crisisCenterModule被预加载,通过该模块可以在控制台看到日志
// html
<p>Dashboard</p>
<p>Session ID: {{ sessionId | async }}</p>
<a id="anchor"></a>
<p>Token: {{ token | async }}</p>
Preloaded Modules
<ul>
<li *ngFor="let module of modules">{{ module }}</li>
</ul>
// ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SelectivePreloadingStrategyService } from '../../selective-preloading-strategy.service';
@Component({
selector: 'app-admin-dashboard',
templateUrl: './admin-dashboard.component.html',
styleUrls: ['./admin-dashboard.component.css']
})
export class AdminDashboardComponent implements OnInit {
sessionId: Observable<string>;
token: Observable<string>;
modules: string[];
constructor(
private route: ActivatedRoute,
preloadStrategy: SelectivePreloadingStrategyService
) {
this.modules = preloadStrategy.preloadedModules;
}
ngOnInit() {
this.sessionId = this.route
.queryParamMap
.pipe(map(params => params.get('session_id') || 'None'));
this.token = this.route
.fragment
.pipe(map(fragment => fragment || 'None'));
}
}
想买的东西很贵,想去的地方很远,喜欢的女孩很完美