Angular

Published on: 28 November 2025

Tags: #javascript


The Problem

The core problem is the exponential complexity of maintaining state-to-view synchronization and architectural consistency in massive applications, where manual (imperative) DOM updates inevitably lead to fragile, unscalable codebases.

The Ivy Engine: LView & TView

classDiagram
    note "Level 2: Ivy Internal Structures (Deep)"

    %% The Static Blueprint
    class TView {
        +firstChild: TNode
        +template: TemplateFn
        +data: Array
        +bindingStartIndex: number
        <>
    }

    %% The Static DOM Definition
    class TNode {
        +index: number
        +tagName: string
        +flags: TNodeFlags
        +next: TNode
        <>
    }

    %% The Runtime Instance
    class LView {
        +Array structure
        ----------------
        [0]: HOST (RNode)
        [1]: TVIEW (Blueprint)
        [9]: INJECTOR (LInjector)
        [20]: HEADER_OFFSET
        [20+]: RNodes & Vars
    }

    %% The actual Native Node
    class RNode {
        <>
    }

    %% Relationships
    TView "1" --* "many" TNode : linked list (firstChild)
    TView "1" -- "many" LView : schemas

    LView --> TView : [1]
    LView --> RNode : [20+]

    %% The Explicit Mapping
    TNode .. RNode : LView[ TNode.index ] === RNode

Compilation: JIT vs AOT & The Instruction Set

flowchart LR
    subgraph Source["Source Code"]
        direction TB
        HTML["template: '
{{val}}
'"] TS["@Component(...) class App { val = 0; }"] end subgraph Compiler["Ivy Compiler (ngtsc)"] direction TB Parse[Parse Template] Check[Type Checking & Analysis] Gen[Generate Instructions] Parse --> Check --> Gen end subgraph Runtime["Runtime Code (AOT)"] direction TB Def["static ɵcmp = defineComponent(...)"] Code["template: function(rf, ctx) { // Phase 1: Creation (Runs ONCE) if (rf & 1) { ɵɵelementStart(0,'div'); ɵɵtext(1); ɵɵelementEnd(); } // Phase 2: Update (Runs on CD) if (rf & 2) { ɵɵadvance(1); ɵɵtextInterpolate(ctx.val); } }"] end Source --> Compiler --> Runtime style Code text-align:left,font-family:monospace

Change Detection: Zone.js vs. Signals

graph TD
    subgraph Zones["Zone.js (ChangeDetectionStrategy.Default)"]
        direction TB
        Event(Click Event) -->|Patched API| Zone[NgZone.onMicrotaskEmpty]
        Zone -->|Triggers| Tick[AppRef.tick]
        Tick -->|1. Check Root| Root[Root Component]
        Root -->|2. Propagate Down| Child1[Child Component]
        Root -->|2. Propagate Down| Child2[Child Component]
        Child1 -->|3. Check| GrandChild1

        style Tick fill:#ffccbc,stroke:#d84315
    end

    subgraph Signals["Signal Graph (Push/Pull System)"]
        direction TB
        S1[("Signal A (Producer)")] 
        C1[("Computed B (Consumer)")]
        E1[("Template Effect (Renderer)")]

        %% The Push Phase
        S1 -.->|1. PUSH: Mark Dirty| C1
        C1 -.->|2. PUSH: Mark Dirty| E1

        %% The Pull Phase
        E1 ==>|3. PULL: Read Value| C1
        C1 ==>|4. PULL: Recalculate| S1

        style S1 fill:#e1f5fe,stroke:#01579b
        style E1 fill:#f9f,stroke:#333
    end

Dependency Injection (DI) Internals

sequenceDiagram
    participant C as Component
    participant NI as NodeInjector (Element)
    participant PI as Parent ElementInjector
    participant RI as Root EnvInjector
    participant PL as PlatformInjector
    participant Null as NullInjector

    Note over C, NI: 1. Element Injector Tree (The DOM)
    C->>NI: Request Service X

    alt Found in Node
        NI-->>C: Return Instance
    else Not Found
        NI->>PI: Bubble up DOM Tree

        alt Found in Parent
            PI-->>C: Return Instance
        else Not Found
            note right of PI: End of DOM Tree.
Bridge to Environment Tree. PI->>RI: Switch Hierarchy Note over RI, Null: 2. Environment Injector Tree (The Module/App) alt Found in App Root RI-->>C: Return Instance else Not Found RI->>PL: Check Platform alt Found in Platform PL-->>C: Return Instance (e.g. DOCUMENT) else Not Found PL->>Null: Last Resort Null-->>C: Throw NullInjectorError end end end end

Bootstrapping Flow

graph TD
    subgraph Platform["Phase 1: Platform (Shared)"]
        direction TB
        P1[platformBrowserDynamic] --> P2[Create PlatformInjector]
        P2 --> P3[Singleton across all apps on page]
    end

    subgraph App["Phase 2: Application (Per App)"]
        direction TB
        B1[bootstrapApplication call] --> B2[Create EnvironmentInjector]
        B2 --> B3[Instantiate ApplicationRef]

        B3 --> Z{Is Zone.js used?}
        Z -->|Yes| Z1[Init NgZone]
        Z -->|No| Z2[Init ɵChangeDetectionScheduler]

        Z1 --> Boot[ApplicationRef.bootstrap]
        Z2 --> Boot
    end

    subgraph Render["Phase 3: Ivy Rendering"]
        direction TB
        Boot --> C1[Resolve Root ComponentFactory]
        C1 --> H{Hydration Enabled?}

        H -->|Yes| H1[Locate Existing DOM Nodes]
        H -->|No| H2[Create New Host Element]

        H1 --> LV[Create Root LView]
        H2 --> LV

        LV --> Tick[First Tick: AppRef.tick]
        Tick --> Listeners[Run APP_BOOTSTRAP_LISTENER]
    end

    style Boot fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style LV fill:#fff9c4,stroke:#fbc02d

Share this post

Share on X  •  Share on LinkedIn  •  Share via Email