# @defer Patterns

Lazy loading strategies and performance optimization.

## Basic Patterns

### Complete State Management

```typescript
@defer (on viewport) {
  <app-product-reviews [productId]="productId()" />
} @placeholder (minimum 500ms) {
  <div class="skeleton" style="height: 400px;"></div>
} @loading (after 100ms; minimum 1s) {
  <mat-spinner />
} @error {
  <p>Failed to load reviews</p>
  <button (click)="retry()">Retry</button>
}
```

## Triggers

### Common Strategies

```typescript
// Idle: Non-critical features
@defer (on idle) { <app-recommendations /> }

// Viewport: Below-the-fold
@defer (on viewport) { <app-comments /> }

// Interaction: User-initiated
@defer (on interaction) { <app-filters /> }

// Hover: Tooltips/popovers
@defer (on hover) { <app-user-tooltip /> }

// Timer: Delayed content
@defer (on timer(3s)) { <app-promo-banner /> }

// When: Custom condition
@defer (when userLoggedIn()) { <app-personalized-content /> }
```

### Multiple Triggers

```typescript
// OR logic: first trigger wins
@defer (on interaction; on timer(5s)) {
  <app-newsletter-signup />
}
```

### Prefetching

```typescript
// Load JS on idle, show on interaction
@defer (on interaction; prefetch on idle) {
  <app-video-player />
}

// Load JS on hover, show on click
@defer (on interaction; prefetch on hover) {
  <app-modal />
}
```

## Performance Patterns

### Bundle Size Reduction

```typescript
<div class="product-page">
  <!-- Critical: Load immediately -->
  <app-product-header [product]="product()" />

  <!-- Heavy chart: Defer on viewport -->
  @defer (on viewport) {
    <app-analytics-chart />
  } @placeholder {
    <div style="height: 300px;"></div>
  }

  <!-- Video player: Defer on interaction -->
  @defer (on interaction; prefetch on idle) {
    <app-video-player />
  } @placeholder {
    <img [src]="videoThumbnail" />
  }
</div>
```

### Staggered Loading

```typescript
<div class="dashboard">
  <app-header /> <!-- Immediate -->

  @defer (on idle) {
    <app-key-metrics /> <!-- Important -->
  }

  @defer (on viewport) {
    <app-recent-activity /> <!-- Secondary -->
  } @placeholder {
    <div style="height: 400px;"></div>
  }

  @defer (on viewport) {
    <app-analytics /> <!-- Tertiary -->
  } @placeholder {
    <div style="height: 300px;"></div>
  }
</div>
```

### Conditional Defer (Mobile Only)

```typescript
// Component
shouldDefer = computed(() => this.breakpoint([Breakpoint.Tablet]));

// Template
@if (shouldDefer()) {
  @defer (on viewport) { <app-heavy-chart /> }
} @else {
  <app-heavy-chart />
}
```

## Requirements

### Must Be Standalone

```typescript
// ✅ Valid
@Component({ standalone: true })
export class ChartComponent {}

@defer { <app-chart /> } // Will defer

// ❌ Invalid
@NgModule({ declarations: [ChartComponent] })
@defer { <app-chart /> } // Won't defer! Loads eagerly
```

### No External References

```typescript
// ❌ Invalid: ViewChild reference
@ViewChild('chart') chart!: ChartComponent;
@defer { <app-chart #chart /> } // ERROR

// ✅ Valid: Use events
@defer {
  <app-chart (dataLoaded)="onChartLoaded($event)" />
}
```

## Core Web Vitals

### Prevent Layout Shift (CLS)

```typescript
// ✅ Reserve exact height
@defer (on viewport) {
  <app-large-component />
} @placeholder {
  <div style="height: 600px;"></div>
}

// ❌ No height reserved
@defer (on viewport) {
  <app-large-component />
} @placeholder {
  <p>Loading...</p> // Causes layout shift
}
```

### Don't Defer LCP Elements

```typescript
// ❌ BAD: Hero image deferred
@defer (on idle) {
  <img src="hero.jpg" /> <!-- LCP element! -->
}

// ✅ GOOD: Load immediately
<img src="hero.jpg" />

@defer (on viewport) {
  <app-below-fold-content />
}
```

### Improve Time to Interactive (TTI)

```typescript
// Critical: Immediate
<button (click)="addToCart()">Add to Cart</button>

// Non-critical: Defer
@defer (on idle) {
  <app-social-share />
}
```

## Common Pitfalls

### 1. Cascading Defer (Bad)

```typescript
// ❌ Sequential loads
@defer (on idle) {
  <div>
    @defer (on idle) {
      <div>
        @defer (on idle) { <app-nested /> }
      </div>
    }
  </div>
}

// ✅ Single defer
@defer (on idle) {
  <div><div><app-nested /></div></div>
}
```

### 2. Above-Fold Defer

```typescript
// ❌ Above-fold content deferred
<header>
  @defer (on idle) {
    <nav>...</nav> <!-- Should load immediately -->
  }
</header>

// ✅ Below-fold only
<header><nav>...</nav></header>
<main>
  @defer (on viewport) {
    <app-below-fold />
  }
</main>
```

### 3. Missing Minimum Durations

```typescript
// ❌ Flickers quickly
@defer {
  <app-fast-component />
} @loading {
  <mat-spinner /> <!-- Flashes briefly -->
}

// ✅ Smooth loading
@defer {
  <app-fast-component />
} @loading (after 100ms; minimum 500ms) {
  <mat-spinner />
}
```

## Real-World Example

```typescript
<div class="product-page">
  <!-- Critical: Immediate -->
  <app-product-header />
  <app-product-images />
  <app-add-to-cart />

  <!-- Important: Idle -->
  @defer (on idle) {
    <app-product-description />
  }

  <!-- Below fold: Viewport -->
  @defer (on viewport) {
    <app-reviews />
  } @placeholder {
    <div style="min-height: 400px;"></div>
  }

  <!-- Optional: Interaction -->
  @defer (on interaction; prefetch on idle) {
    <app-size-guide />
  } @placeholder {
    <button>View Size Guide</button>
  }

  <!-- Related: Viewport -->
  @defer (on viewport) {
    <app-related-products />
  }
</div>
```
