性能优化 #

一、性能优化概述 #

Angular性能优化主要关注以下几个方面:

  • 变更检测优化
  • 模块懒加载
  • 编译优化
  • 运行时优化
  • 内存管理

二、变更检测优化 #

2.1 使用OnPush策略 #

typescript
import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-user-list',
  template: `
    <app-user-card 
      *ngFor="let user of users"
      [user]="user">
    </app-user-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserListComponent {
  @Input() users: User[];
}

2.2 OnPush触发条件 #

  • 输入属性引用变化
  • 组件内部触发事件
  • 手动触发变更检测
  • Async管道订阅的Observable发出新值

2.3 不可变数据 #

typescript
// 推荐:创建新引用
addUser(user: User) {
  this.users = [...this.users, user];
}

updateUser(updatedUser: User) {
  this.users = this.users.map(user => 
    user.id === updatedUser.id ? updatedUser : user
  );
}

// 不推荐:直接修改
addUser(user: User) {
  this.users.push(user);
}

2.4 使用markForCheck #

typescript
import { Component, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '{{ data }}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleComponent {
  data: string;
  
  constructor(private cdr: ChangeDetectorRef) {}
  
  updateData() {
    this.data = 'new value';
    this.cdr.markForCheck();
  }
}

2.5 使用detach/reattach #

typescript
@Component({
  selector: 'app-heavy',
  template: '...'
})
export class HeavyComponent implements OnInit {
  constructor(private cdr: ChangeDetectorRef) {}
  
  ngOnInit() {
    this.cdr.detach();
    
    setInterval(() => {
      this.cdr.reattach();
      this.cdr.detectChanges();
      this.cdr.detach();
    }, 1000);
  }
}

三、模板优化 #

3.1 使用trackBy #

typescript
@Component({
  template: `
    <li *ngFor="let user of users; trackBy: trackById">
      {{ user.name }}
    </li>
  `
})
export class UserListComponent {
  trackById(index: number, user: User): number {
    return user.id;
  }
}

3.2 避免复杂表达式 #

html
<!-- 不推荐 -->
<div>{{ formatName(user.firstName, user.lastName, user.middleName) }}</div>

<!-- 推荐:预先计算 -->
<div>{{ user.fullName }}</div>

3.3 使用纯管道 #

typescript
@Pipe({
  name: 'formatDate',
  pure: true
})
export class FormatDatePipe implements PipeTransform {
  transform(value: Date): string {
    return value.toLocaleDateString();
  }
}

3.4 减少模板绑定 #

html
<!-- 不推荐 -->
<div [style.color]="color" [style.background]="bg" [style.padding]="padding">
  {{ content }}
</div>

<!-- 推荐 -->
<div [ngStyle]="styles">{{ content }}</div>

四、懒加载优化 #

4.1 路由懒加载 #

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

4.2 组件懒加载 #

typescript
@Component({
  template: `
    <ng-template #container></ng-template>
  `
})
export class LazyComponent {
  @ViewChild('container', { read: ViewContainerRef }) container!: ViewContainerRef;
  
  async loadComponent() {
    const { HeavyComponent } = await import('./heavy.component');
    this.container.createComponent(HeavyComponent);
  }
}

4.3 预加载策略 #

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

五、编译优化 #

5.1 AOT编译 #

bash
ng build --aot

5.2 生产构建 #

bash
ng build --configuration production

5.3 构建优化选项 #

json
{
  "optimization": true,
  "buildOptimizer": true,
  "aot": true,
  "sourceMap": false,
  "extractLicenses": true,
  "vendorChunk": false,
  "commonChunk": false
}

5.4 Budget配置 #

json
{
  "budgets": [
    {
      "type": "initial",
      "maximumWarning": "500kb",
      "maximumError": "1mb"
    },
    {
      "type": "anyComponentStyle",
      "maximumWarning": "2kb",
      "maximumError": "4kb"
    }
  ]
}

六、内存优化 #

6.1 取消订阅 #

typescript
export class ExampleComponent implements OnInit, OnDestroy {
  private destroy$ = new Subject<void>();
  
  ngOnInit() {
    this.service.getData()
      .pipe(takeUntil(this.destroy$))
      .subscribe();
  }
  
  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

6.2 清理定时器 #

typescript
export class ExampleComponent implements OnInit, OnDestroy {
  private timer: any;
  
  ngOnInit() {
    this.timer = setInterval(() => {}, 1000);
  }
  
  ngOnDestroy() {
    clearInterval(this.timer);
  }
}

6.3 清理事件监听 #

typescript
export class ExampleComponent implements OnInit, OnDestroy {
  private listener: () => void;
  
  constructor(private renderer: Renderer2, private element: ElementRef) {}
  
  ngOnInit() {
    this.listener = this.renderer.listen(
      this.element.nativeElement,
      'click',
      this.onClick
    );
  }
  
  ngOnDestroy() {
    this.listener();
  }
}

七、网络优化 #

7.1 HTTP缓存 #

typescript
@Injectable()
export class CacheInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const cachedResponse = this.cache.get(req.url);
    if (cachedResponse) {
      return of(cachedResponse);
    }
    
    return next.handle(req).pipe(
      tap(event => {
        if (event instanceof HttpResponse) {
          this.cache.set(req.url, event);
        }
      })
    );
  }
}

7.2 请求合并 #

typescript
getUsers(ids: number[]): Observable<User[]> {
  const requests = ids.map(id => this.http.get<User>(`/api/users/${id}`));
  return forkJoin(requests);
}

7.3 请求取消 #

typescript
export class SearchComponent implements OnDestroy {
  private searchSubject = new Subject<string>();
  private destroy$ = new Subject<void>();
  
  constructor(private http: HttpClient) {
    this.searchSubject.pipe(
      debounceTime(300),
      switchMap(query => this.http.get(`/api/search?q=${query}`)),
      takeUntil(this.destroy$)
    ).subscribe();
  }
  
  search(query: string) {
    this.searchSubject.next(query);
  }
  
  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

八、图片优化 #

8.1 图片懒加载 #

typescript
@Directive({
  selector: '[appLazyLoad]',
  standalone: true
})
export class LazyLoadDirective implements OnInit {
  @Input() appLazyLoad: string;
  
  constructor(private el: ElementRef) {}
  
  ngOnInit() {
    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          this.el.nativeElement.src = this.appLazyLoad;
          observer.unobserve(this.el.nativeElement);
        }
      });
    });
    
    observer.observe(this.el.nativeElement);
  }
}

8.2 使用NgOptimizedImage #

typescript
import { NgOptimizedImage } from '@angular/common';

@Component({
  imports: [NgOptimizedImage],
  template: `
    <img 
      ngSrc="assets/image.jpg" 
      alt="描述"
      width="800"
      height="600"
      priority
    />
  `
})

九、性能监控 #

9.1 使用Angular DevTools #

bash
# 安装Angular DevTools浏览器扩展

9.2 性能指标 #

typescript
// 使用Performance API
const start = performance.now();
// 执行操作
const end = performance.now();
console.log(`耗时: ${end - start}ms`);

9.3 变更检测周期 #

typescript
import { ApplicationRef } from '@angular/core';

constructor(private appRef: ApplicationRef) {
  this.appRef.isStable.subscribe(stable => {
    console.log('应用稳定:', stable);
  });
}

十、优化检查清单 #

10.1 变更检测 #

  • [ ] 使用OnPush策略
  • [ ] 使用trackBy
  • [ ] 避免复杂模板表达式
  • [ ] 使用纯管道

10.2 编译 #

  • [ ] 启用AOT编译
  • [ ] 生产构建优化
  • [ ] 配置Budgets

10.3 网络 #

  • [ ] 启用懒加载
  • [ ] 配置预加载
  • [ ] HTTP缓存
  • [ ] 请求取消

10.4 内存 #

  • [ ] 取消订阅
  • [ ] 清理定时器
  • [ ] 清理事件监听

十一、总结 #

优化方向 策略
变更检测 OnPush、trackBy、纯管道
模板优化 简化表达式、减少绑定
懒加载 路由懒加载、组件懒加载
编译优化 AOT、生产构建
内存优化 取消订阅、清理资源
网络优化 缓存、请求合并

恭喜完成Angular完全指南!

最后更新:2026-03-26