结合路由守卫控制懒加载模块加载
- CanLoad 守卫:
- 原理:
CanLoad
守卫用于在模块被加载之前决定是否允许加载该模块。它作用于路由配置中的 loadChildren
属性对应的懒加载模块。
- 使用方法:
- 创建一个实现
CanLoad
接口的守卫类,例如:
import { Injectable } from '@angular/core';
import { CanLoad, Route, UrlSegment, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthCanLoadGuard implements CanLoad {
constructor(private authService: AuthService, private router: Router) {}
canLoad(route: Route, segments: UrlSegment[]): boolean | Promise<boolean> | Observable<boolean> {
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
- 在路由配置中使用该守卫:
const routes: Routes = [
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
canLoad: [AuthCanLoadGuard]
}
];
- CanActivate 守卫与延迟加载配合:
- 原理:虽然
CanActivate
主要用于决定是否可以激活路由,但结合懒加载模块,它可以在模块加载并激活路由之前进行条件判断。
- 使用方法:
- 创建实现
CanActivate
接口的守卫类,示例如下:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthCanActivateGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Promise<boolean> | Observable<boolean> {
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
- 在路由配置中使用:
const routes: Routes = [
{
path: 'user',
loadChildren: () => import('./user/user.module').then(m => m.UserModule),
canActivate: [AuthCanActivateGuard]
}
];
监控懒加载优化前后应用性能指标变化
- 加载时间监控:
- 懒加载前:
- 使用浏览器开发者工具(如 Chrome DevTools)的 Performance 面板。在页面加载前开启录制,页面加载完成后停止录制,从时间轴中获取页面整体加载时间,包括所有初始加载的模块。
- 在代码中使用
performance.now()
方法记录关键时间点。例如,在 ngOnInit
钩子函数开始处记录开始时间 const startTime = performance.now();
,在 ngOnInit
结束处记录结束时间 const endTime = performance.now();
,计算差值 const loadTime = endTime - startTime;
来获取组件加载时间。
- 懒加载后:
- 同样使用浏览器开发者工具的 Performance 面板,但重点关注懒加载模块加载的时间段。通过筛选事件类型(如
Resource Fetching
中的 script
加载事件)来确定懒加载模块的加载时间。
- 在懒加载模块的
loadChildren
回调函数开始和结束处使用 performance.now()
记录时间。例如:
loadChildren: () => {
const startTime = performance.now();
return import('./lazy - loaded - module/lazy - loaded - module.module').then(m => {
const endTime = performance.now();
const loadTime = endTime - startTime;
console.log('Lazy - loaded module load time:', loadTime);
return m.LazyLoadedModule;
});
}
- 内存占用监控:
- 懒加载前:
- 使用浏览器开发者工具的 Memory 面板。在页面加载完成后,进行一次内存快照(
Take Snapshot
),记录下初始内存占用情况,包括所有初始加载模块占用的内存。
- 可以在代码中通过
WeakMap
和 WeakSet
来跟踪对象引用,间接了解内存使用情况。例如,创建一个 WeakMap
用于存储对象引用:const objectMap = new WeakMap();
,当对象创建时添加到 WeakMap
中 objectMap.set(newObject, true);
,观察 WeakMap
的大小变化来推测内存中对象数量的变化。
- 懒加载后:
- 先在懒加载模块未加载时进行一次内存快照记录基础内存占用。然后加载懒加载模块,再次进行内存快照,对比两次快照中内存占用的差值,即为懒加载模块带来的内存变化。
- 对于懒加载模块内部,可以在模块的生命周期钩子函数(如
ngOnDestroy
)中检查对象是否被正确释放。例如,在 ngOnDestroy
中检查是否有未释放的定时器、事件监听器等,确保内存得到合理释放。
- 性能指标统计与报告:
- 创建一个性能监控服务,例如
PerformanceMonitoringService
。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PerformanceMonitoringService {
private loadTimes: { [key: string]: number } = {};
private memoryUsages: { [key: string]: number } = {};
recordLoadTime(moduleName: string, loadTime: number) {
this.loadTimes[moduleName] = loadTime;
}
recordMemoryUsage(moduleName: string, memoryUsage: number) {
this.memoryUsages[moduleName] = memoryUsage;
}
generateReport() {
console.log('Performance Report:');
console.log('Load Times:');
for (const module in this.loadTimes) {
if (this.loadTimes.hasOwnProperty(module)) {
console.log(`${module}: ${this.loadTimes[module]} ms`);
}
}
console.log('Memory Usages:');
for (const module in this.memoryUsages) {
if (this.memoryUsages.hasOwnProperty(module)) {
console.log(`${module}: ${this.memoryUsages[module]} bytes`);
}
}
}
}
- 在应用合适的地方(如懒加载模块加载完成后、组件销毁时等)调用该服务的方法记录性能指标,并在需要时生成性能报告。例如,在懒加载模块加载完成的回调函数中:
loadChildren: () => {
const startTime = performance.now();
return import('./lazy - loaded - module/lazy - loaded - module.module').then(m => {
const endTime = performance.now();
const loadTime = endTime - startTime;
this.performanceMonitoringService.recordLoadTime('LazyLoadedModule', loadTime);
// 假设获取内存使用量的函数 getMemoryUsage
const memoryUsage = getMemoryUsage();
this.performanceMonitoringService.recordMemoryUsage('LazyLoadedModule', memoryUsage);
return m.LazyLoadedModule;
});
}
- 在应用的某个入口点(如 `AppComponent` 的 `ngOnInit` 中)调用 `generateReport` 方法生成性能报告:
import { Component } from '@angular/core';
import { PerformanceMonitoringService } from './performance - monitoring.service';
@Component({
selector: 'app - root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private performanceMonitoringService: PerformanceMonitoringService) {}
ngOnInit() {
this.performanceMonitoringService.generateReport();
}
}