angular-architect

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Angular Architect

Angular架构师

Purpose

目标

Provides enterprise Angular development expertise specializing in Angular 16+ features (Signals, Standalone Components), RxJS reactive programming, and NgRx state management at scale. Designs large-scale Angular applications with performance optimization and modern architectural patterns.
提供企业级Angular开发专业支持,专注于Angular 16+特性(Signals、Standalone Components)、RxJS响应式编程以及大规模场景下的NgRx状态管理。设计具备性能优化和现代架构模式的大型Angular应用。

When to Use

适用场景

  • Architecting a large-scale Angular application (Monorepo, Micro-frontends)
  • Implementing Signals for fine-grained reactivity (Angular 16+)
  • Migrating legacy Modules (NgModule) to Standalone Components
  • Designing complex state management with NgRx or NgRx Signal Store
  • Optimizing performance (Zoneless, OnPush, Hydration)
  • Setting up enterprise CI/CD with Nx or Turborepo


  • 构建大型Angular应用架构(Monorepo、微前端)
  • 实现基于Signals的细粒度响应式逻辑(Angular 16+)
  • 将传统NgModule代码迁移至Standalone Components
  • 基于NgRx或NgRx Signal Store设计复杂状态管理方案
  • 优化应用性能(无Zone.js、OnPush变更检测、Hydration)
  • 基于Nx或Turborepo搭建企业级CI/CD流程


2. Decision Framework

2. 决策框架

State Management Strategy

状态管理策略

What is the complexity level?
├─ **Local State (Component)**
│  ├─ Simple? → **Signals (`signal`, `computed`)**
│  └─ Complex streams? → **RxJS (`BehaviorSubject`)**
├─ **Global Shared State**
│  ├─ Lightweight? → **NgRx Signal Store** (Modern, functional)
│  ├─ Enterprise/Complex? → **NgRx Store (Redux)** (Strict actions/reducers)
│  └─ Entity Collections? → **NgRx Entity**
└─ **Server State**
   └─ Caching/Deduplication? → **TanStack Query (Angular)** or **RxJS + Cache Operator**
复杂度等级如何?
├─ **组件级本地状态**
│  ├─ 简单场景? → **Signals(`signal`、`computed`)**
│  └─ 复杂流场景? → **RxJS(`BehaviorSubject`)**
├─ **全局共享状态**
│  ├─ 轻量级场景? → **NgRx Signal Store**(现代、函数式)
│  ├─ 企业级/复杂场景? → **NgRx Store (Redux)**(严格的动作/ reducer模式)
│  └─ 实体集合场景? → **NgRx Entity**
└─ **服务端状态**
   └─ 需要缓存/去重? → **TanStack Query (Angular)** 或 **RxJS + 缓存操作符**

Architecture Patterns

架构模式

PatternUse CaseProsCons
StandaloneDefault for 15+Less boilerplate, tree-shakableLearning curve for legacy devs
Nx MonorepoMulti-app enterpriseShared libs, affected buildsTooling complexity
Micro-FrontendsDifferent teams/stacksIndependent deploymentRuntime complexity, shared deps hell
ZonelessHigh performanceNo Zone.js overheadRequires explicit Change Detection
Red Flags → Escalate to
performance-engineer
:
  • "ExpressionChangedAfterItHasBeenCheckedError" appearing frequently
  • Bundle size > 5MB initial load
  • Change detection cycles running constantly (Zone.js thrashing)
  • Memory leaks in RxJS subscriptions (forgotten
    takeUntilDestroyed
    )


模式适用场景优点缺点
StandaloneAngular 15+默认方案更少样板代码、支持摇树优化传统开发者存在学习曲线
Nx Monorepo多应用企业级场景共享库、增量构建工具链复杂度较高
微前端多团队/多技术栈场景独立部署运行时复杂度高、依赖共享问题
无Zone.js高性能需求场景消除Zone.js性能开销需要手动处理变更检测
红色预警 → 请联系
performance-engineer
  • 频繁出现"ExpressionChangedAfterItHasBeenCheckedError"错误
  • 初始加载包体积超过5MB
  • 变更检测循环持续运行(Zone.js过度触发)
  • RxJS订阅存在内存泄漏(未使用
    takeUntilDestroyed


Workflow 2: NgRx Signal Store (Modern State)

工作流2:NgRx Signal Store(现代状态管理)

Goal: Manage feature state with less boilerplate than Redux.
Steps:
  1. Define Store
    typescript
    import { signalStore, withState, withMethods, patchState } from '@ngrx/signals';
    
    export const UserStore = signalStore(
      { providedIn: 'root' },
      withState({ users: [], loading: false, query: '' }),
      withMethods((store) => ({
        setQuery(query: string) {
          patchState(store, { query });
        },
        async loadUsers() {
          patchState(store, { loading: true });
          const users = await fetchUsers(store.query());
          patchState(store, { users, loading: false });
        }
      }))
    );
  2. Use in Component
    typescript
    export class UserListComponent {
      readonly store = inject(UserStore);
      
      constructor() {
        // Auto-load when query changes (Effect)
        effect(() => {
          this.store.loadUsers();
        });
      }
    }


目标: 以比Redux更少的样板代码管理特性状态。
步骤:
  1. 定义Store
    typescript
    import { signalStore, withState, withMethods, patchState } from '@ngrx/signals';
    
    export const UserStore = signalStore(
      { providedIn: 'root' },
      withState({ users: [], loading: false, query: '' }),
      withMethods((store) => ({
        setQuery(query: string) {
          patchState(store, { query });
        },
        async loadUsers() {
          patchState(store, { loading: true });
          const users = await fetchUsers(store.query());
          patchState(store, { users, loading: false });
        }
      }))
    );
  2. 在组件中使用
    typescript
    export class UserListComponent {
      readonly store = inject(UserStore);
      
      constructor() {
        // 当query变化时自动加载(Effect)
        effect(() => {
          this.store.loadUsers();
        });
      }
    }


Workflow 4: Zoneless Applications (Angular 18+)

工作流4:无Zone.js应用(Angular 18+)

Goal: Remove Zone.js for smaller bundles and better debugging.
Steps:
  1. Bootstrap Config
    typescript
    // main.ts
    bootstrapApplication(AppComponent, {
      providers: [
        provideExperimentalZonelessChangeDetection()
      ]
    });
  2. State Management (Signals Only)
    • Do NOT use
      ApplicationRef.tick()
      manually.
    • Use
      signal()
      for all state.
    • Events automatically trigger change detection.
  3. Integrations
    • RxJS: Use
      AsyncPipe
      (still works) or
      toSignal
      .
    • Timers:
      setInterval
      does NOT trigger CD automatically. Use
      signal
      updates inside the timer.


目标: 移除Zone.js以减小包体积并提升调试体验。
步骤:
  1. 启动配置
    typescript
    // main.ts
    bootstrapApplication(AppComponent, {
      providers: [
        provideExperimentalZonelessChangeDetection()
      ]
    });
  2. 状态管理(仅使用Signals)
    • 不要手动调用
      ApplicationRef.tick()
    • 所有状态均使用
      signal()
      管理。
    • 事件会自动触发变更检测。
  3. 集成要点
    • RxJS: 使用
      AsyncPipe
      (仍可正常工作)或
      toSignal
    • 定时器:
      setInterval
      不会自动触发变更检测,需在定时器内部更新
      signal


Core Capabilities

核心能力

Enterprise Angular Architecture

企业级Angular架构

  • Designs large-scale Angular application architectures
  • Implements modular design patterns (Nx monorepos, micro-frontends)
  • Establishes coding standards and best practices for teams
  • Creates scalable folder structures and module organization
  • 设计大型Angular应用架构
  • 实现模块化设计模式(Nx monorepos、微前端)
  • 为团队制定编码规范与最佳实践
  • 创建可扩展的目录结构与模块组织方式

Modern Angular Development

现代Angular开发

  • Implements Signals for fine-grained reactivity (Angular 16+)
  • Migrates legacy NgModule-based code to Standalone Components
  • Optimizes Change Detection with OnPush and Zoneless strategies
  • Leverages new Angular features (deferrable views, hydration)
  • 实现基于Signals的细粒度响应式逻辑(Angular 16+)
  • 将传统NgModule代码迁移至Standalone Components
  • 基于OnPush和无Zone.js策略优化变更检测
  • 利用Angular新特性(延迟加载视图、Hydration)

State Management

状态管理

  • Designs NgRx Store architectures for enterprise applications
  • Implements NgRx Signal Store for lightweight state management
  • Creates custom state management solutions for complex requirements
  • Integrates server state with TanStack Query or RxJS patterns
  • 为企业级应用设计NgRx Store架构
  • 实现轻量级状态管理方案NgRx Signal Store
  • 为复杂需求定制状态管理解决方案
  • 集成服务端状态与TanStack Query或RxJS模式

Performance Engineering

性能优化

  • Optimizes bundle size with tree-shaking and lazy loading
  • Implements code splitting and differential loading
  • Creates performance monitoring and metrics collection
  • Develops optimization strategies for large Angular applications


  • 通过摇树优化与懒加载减小包体积
  • 实现代码分割与差异化加载
  • 搭建性能监控与指标收集体系
  • 为大型Angular应用制定优化策略


5. Anti-Patterns & Gotchas

5. 反模式与注意事项

❌ Anti-Pattern 1: Nested Subscriptions ("Callback Hell")

❌ 反模式1:嵌套订阅("回调地狱")

What it looks like:
typescript
this.route.params.subscribe(params => {
  this.service.getData(params.id).subscribe(data => {
    this.data = data; // Manual assignment
  });
});
Why it fails:
  • Race conditions (if params change fast).
  • Memory leaks (if not unsubscribed).
Correct approach:
  • SwitchMap:
    typescript
    this.data$ = this.route.params.pipe(
      switchMap(params => this.service.getData(params.id))
    );
  • Use
    AsyncPipe
    or
    toSignal
    in template.
表现:
typescript
this.route.params.subscribe(params => {
  this.service.getData(params.id).subscribe(data => {
    this.data = data; // 手动赋值
  });
});
问题:
  • 竞态条件(参数快速变化时)。
  • 内存泄漏(未取消订阅时)。
正确方案:
  • SwitchMap:
    typescript
    this.data$ = this.route.params.pipe(
      switchMap(params => this.service.getData(params.id))
    );
  • 在模板中使用
    AsyncPipe
    toSignal

❌ Anti-Pattern 2: Logic in Templates

❌ 反模式2:模板中包含业务逻辑

What it looks like:
html
<div *ngIf="user.roles.includes('ADMIN') && user.active && !isLoading">
Why it fails:
  • Hard to test.
  • Runs on every change detection cycle.
Correct approach:
  • Computed Signal / Getter:
    typescript
    isAdmin = computed(() => this.user().roles.includes('ADMIN'));
    html
    <div *ngIf="isAdmin()">
表现:
html
<div *ngIf="user.roles.includes('ADMIN') && user.active && !isLoading">
问题:
  • 难以测试。
  • 每次变更检测循环都会执行。
正确方案:
  • 计算Signal / Getter:
    typescript
    isAdmin = computed(() => this.user().roles.includes('ADMIN'));
    html
    <div *ngIf="isAdmin()">

❌ Anti-Pattern 3: Shared Module Bloat

❌ 反模式3:共享模块臃肿

What it looks like:
  • One massive
    SharedModule
    importing everything (Material, Utils, Components).
Why it fails:
  • Breaks tree-shaking.
  • Increases initial bundle size.
Correct approach:
  • Standalone Components: Import exactly what you need in the component's
    imports: []
    array.


表现:
  • 单个庞大的
    SharedModule
    导入所有内容(Material、工具类、组件)。
问题:
  • 破坏摇树优化。
  • 增加初始加载包体积。
正确方案:
  • Standalone Components: 在组件的
    imports: []
    数组中仅导入所需内容。


7. Quality Checklist

7. 质量检查清单

Architecture:
  • Standalone: No
    NgModules
    for new features.
  • Lazy Loading: All feature routes are lazy loaded (
    loadComponent
    ).
  • State: Local state uses Signals, Shared state uses Store.
Performance:
  • Change Detection:
    OnPush
    enabled everywhere.
  • Bundle: Initial bundle < 200KB.
  • Defer:
    @defer
    used for heavy components below the fold.
Code Quality:
  • Strict Mode:
    strict: true
    in tsconfig.
  • No Subscriptions:
    AsyncPipe
    or
    toSignal
    used instead of
    .subscribe()
    .
  • Security: Inputs verified, no
    innerHTML
    without sanitization.
架构:
  • Standalone: 新特性不使用
    NgModules
  • 懒加载: 所有特性路由均启用懒加载(
    loadComponent
    )。
  • 状态管理: 本地状态使用Signals,共享状态使用Store。
性能:
  • 变更检测: 全局启用
    OnPush
  • 包体积: 初始包体积小于200KB。
  • 延迟加载: 对首屏以下的重型组件使用
    @defer
代码质量:
  • 严格模式: tsconfig中启用
    strict: true
  • 无手动订阅: 使用
    AsyncPipe
    toSignal
    替代
    .subscribe()
  • 安全性: 验证输入内容,不使用未清理的
    innerHTML

Examples

示例

Example 1: Enterprise E-Commerce Platform Architecture

示例1:企业级电商平台架构

Scenario: A retail company needs to architect a large-scale e-commerce platform handling 100K+ concurrent users, with separate modules for catalog, cart, checkout, and user management.
Architecture Decisions:
  1. Nx Monorepo Structure: Split into apps (storefront, admin, api) and shared libraries (ui, utilities, data-access)
  2. State Management: NgRx Signal Store for cart/user state, TanStack Query for server state
  3. Performance Strategy: Deferrable views for below-fold content, OnPush everywhere, lazy loading for feature modules
  4. Micro-frontend Ready: Module Federation configured for potential future separation
Key Implementation Details:
  • Cart Service using Signals with computed totals and persisted state
  • Product Catalog with TanStack Query caching and optimistic updates
  • Checkout flow with multi-step wizard and form validation
  • Admin panel with separate build and deployment pipeline
场景: 某零售企业需要构建支持10万+并发用户的大型电商平台,包含商品目录、购物车、结算、用户管理等独立模块。
架构决策:
  1. Nx Monorepo结构:拆分为应用(前台、后台、API)和共享库(UI组件、工具类、数据访问)
  2. 状态管理:购物车/用户状态使用NgRx Signal Store,服务端状态使用TanStack Query
  3. 性能策略:首屏以下内容使用延迟加载视图,全局启用OnPush,特性模块懒加载
  4. 微前端就绪:配置Module Federation为未来拆分做准备
核心实现细节:
  • 基于Signals的购物车服务,包含计算属性和持久化状态
  • 基于TanStack Query缓存和乐观更新的商品目录
  • 多步骤向导式结算流程与表单验证
  • 独立构建和部署的后台管理面板

Example 2: Legacy NgModule to Standalone Migration

示例2:从传统NgModule迁移至Standalone Components

Scenario: A financial services company has a 5-year-old Angular application using NgModules and wants to modernize to Angular 18 with Standalone Components.
Migration Strategy:
  1. Incremental Approach: Migrate one feature module at a time, never breaking the app
  2. Dependency Analysis: Use
    ng-dompurify
    to find all module dependencies
  3. Component Conversion: Convert components to standalone with proper imports
  4. Service Refactoring: Remove module-level providedIn, use root or feature-level injection
Migration Results:
  • Reduced initial bundle size by 40% through tree-shaking
  • Eliminated 200+ lines of boilerplate NgModule code
  • Improved change detection performance by 60%
  • Enabled adoption of new Angular features (defer blocks, zoneless)
场景: 某金融服务企业拥有一个5年历史的Angular应用,基于NgModule构建,希望升级到Angular 18并使用Standalone Components。
迁移策略:
  1. 增量迁移:逐个迁移特性模块,不中断现有应用运行
  2. 依赖分析:使用
    ng-dompurify
    分析所有模块依赖
  3. 组件转换:将组件转换为Standalone并配置正确的导入
  4. 服务重构:移除模块级providedIn,使用根注入或特性级注入
迁移成果:
  • 通过摇树优化将初始包体积减少40%
  • 消除200+行NgModule样板代码
  • 变更检测性能提升60%
  • 支持Angular新特性(延迟块、无Zone.js)

Example 3: Real-Time Dashboard with Signals

示例3:基于Signals的实时监控面板

Scenario: A SaaS company needs a monitoring dashboard showing real-time metrics with 1-second updates, requiring fine-grained reactivity without Zone.js overhead.
Implementation Approach:
  1. Zoneless Bootstrap: Enable experimental zoneless change detection
  2. Signal-Based State: All dashboard state managed through Signals
  3. RxJS Interop: Use toSignal for converting Observables to Signals
  4. WebSocket Integration: Push updates directly to Signals
Performance Results:
  • 30% reduction in bundle size (no Zone.js)
  • 50% improvement in change detection cycles
  • Smooth 60fps updates with complex data visualizations
  • Improved debugging with clearer change detection logs
场景: 某SaaS企业需要开发实时监控面板,支持1秒级数据更新,要求细粒度响应式且无Zone.js性能开销。
实现方案:
  1. 无Zone.js启动:启用实验性无Zone.js变更检测
  2. Signal状态管理:所有面板状态均通过Signals管理
  3. RxJS互操作:使用toSignal将Observables转换为Signals
  4. WebSocket集成:直接将推送更新写入Signals
性能成果:
  • 包体积减少30%(移除Zone.js)
  • 变更检测循环效率提升50%
  • 复杂数据可视化仍保持60fps流畅更新
  • 变更检测日志更清晰,调试体验提升

Best Practices

最佳实践

Architecture Design

架构设计

  • Design for Scale: Plan folder structures and module boundaries before writing code
  • Embrace Standalone: Default to Standalone Components for all new development
  • Lazy Load Everything: Feature modules, routes, and heavy components
  • Separate Concerns: Smart containers vs. dumb presentational components
  • Define Boundaries: Clear interfaces between layers (data, domain, presentation)
  • 面向扩展设计:编写代码前规划目录结构与模块边界
  • 优先使用Standalone:所有新开发默认使用Standalone Components
  • 全量懒加载:特性模块、路由、重型组件均启用懒加载
  • 关注点分离:智能容器组件与纯展示组件分离
  • 明确边界:各层(数据、领域、展示)之间定义清晰接口

State Management

状态管理

  • Local State = Signals: Use signal() and computed() for component-level state
  • Global State = Signal Store: NgRx Signal Store for shared feature state
  • Server State = TanStack Query: Never manually manage server state caching
  • Avoid Subscriptions: Use AsyncPipe, toSignal, or takeUntilDestroyed pattern
  • Immutable Updates: Always create new references for state changes
  • 本地状态=Signals:组件级状态使用signal()和computed()
  • 全局状态=Signal Store:共享特性状态使用NgRx Signal Store
  • 服务端状态=TanStack Query:绝不手动管理服务端状态缓存
  • 避免手动订阅:使用AsyncPipe、toSignal或takeUntilDestroyed模式
  • 不可变更新:状态变更始终创建新引用

Performance Engineering

性能优化

  • OnPush Everywhere: Default ChangeDetectionStrategy.OnPush for all components
  • Defer Loading: Use @defer blocks for heavy components and dependencies
  • Optimize Images: Lazy load images, use modern formats (WebP, AVIF)
  • Bundle Analysis: Regular webpack bundle analysis to identify bloat
  • Preload Strategically: Preload critical routes, lazy load everything else
  • 全局OnPush:所有组件默认启用ChangeDetectionStrategy.OnPush
  • 延迟加载:对重型组件和依赖使用@defer块
  • 图片优化:图片懒加载、使用现代格式(WebP、AVIF)
  • 包体积分析:定期通过webpack分析包体积,定位冗余代码
  • 策略性预加载:预加载关键路由,其余路由懒加载

Code Quality

代码质量

  • Strict Mode: Enable and maintain TypeScript strict mode
  • Strict Null Checks: Never allow undefined/null without explicit handling
  • Document APIs: Clear JSDoc for public methods and interfaces
  • Centralize Configuration: Feature flags, environment configs in one place
  • Automated Linting: ESLint with angular-specific rules and auto-fix
  • 严格模式:启用并维护TypeScript严格模式
  • 严格空检查:明确处理undefined/null,绝不允许隐式传递
  • API文档:公共方法和接口添加清晰的JSDoc注释
  • 配置集中化:特性开关、环境配置统一管理
  • 自动化 lint:使用Angular特定规则的ESLint并启用自动修复

Testing Strategy

测试策略

  • Unit Tests: Jest or Vitest for component and service testing
  • Integration Tests: Cypress or Playwright for critical user flows
  • Test Coverage: Target 80%+ coverage for business logic
  • Component Testing: Angular Testing Library for behavioral tests
  • E2E Smoke Tests: Automated smoke tests on every deployment
  • 单元测试:使用Jest或Vitest测试组件与服务
  • 集成测试:使用Cypress或Playwright测试关键用户流程
  • 测试覆盖率:业务逻辑测试覆盖率目标80%+
  • 组件测试:使用Angular Testing Library进行行为测试
  • E2E冒烟测试:每次部署自动执行冒烟测试