Skip to content
intermediate Phase 11 · Signals and Change Detection

Deferred Loading with @defer

Load heavy template content only when a trigger fires.

35m
0 problems
Topic Progress 0%

Basic @defer Usage

@defer loads its template only when the trigger condition is met, reducing initial bundle size and improving page load.

Basic @defer

@Component({
  selector: 'app-dashboard',
  template: `
    <h1>Dashboard</h1>

    @defer {
      <app-heavy-chart />
    } @placeholder {
      <p>Chart will appear here...</p>
    }
  `,
})
export class DashboardComponent {}

@defer Blocks

@defer {
  <!-- Main content: loaded when trigger fires -->
  <app-heavy-component />
} @placeholder {
  <!-- Shown before the trigger fires -->
  <p>Loading...</p>
} @loading {
  <!-- Shown while the deferred chunk downloads -->
  <p>Downloading...</p>
} @error {
  <!-- Shown if loading fails -->
  <p>Failed to load component</p>
}

Trigger Types

Trigger When It Fires
@defer (default) When the browser is idle
@defer (on idle) When the browser is idle
@defer (on viewport) When the element enters the viewport
@defer (on interaction) When the user clicks/taps the placeholder
@defer (on hover) When the user hovers the placeholder
@defer (on timer) After a specified delay
@defer (on immediate) Immediately after the page loads

Defer Triggers in Detail

Triggers control when deferred content loads. Choose the right trigger for each scenario.

viewport Trigger

Loads when the element enters the viewport (uses Intersection Observer):

@defer (on viewport) {
  <app-image-gallery />
} @placeholder {
  <div class="skeleton-loader"></div>
}

interaction Trigger

Loads when the user interacts with the placeholder:

@defer (on interaction) {
  <app-comments />
} @placeholder {
  <button>Load Comments</button>
}

timer Trigger

Loads after a specified delay:

@defer (on timer(5s)) {
  <app-newsletter-signup />
} @placeholder {
  <p>Newsletter will appear in 5 seconds...</p>
}

hover Trigger

Loads when the user hovers over the placeholder:

@defer (on hover) {
  <app-tooltip-content />
} @placeholder {
  <span>Hover for details</span>
}

Combining Triggers

@defer (on interaction; on timer(10s)) {
  <app-recommendations />
} @placeholder {
  <p>Click here or wait 10 seconds</p>
}

Practical Example: E-commerce Product Page

<div class="product-page">
  <h1>{{ product.name }}</h1>
  <p>{{ product.price | currency }}</p>

  <!-- Heavy reviews section deferred until visible -->
  @defer (on viewport) {
    <app-product-reviews [productId]="product.id" />
  } @placeholder {
    <div class="reviews-skeleton"></div>
  }

  <!-- Newsletter signup deferred until idle -->
  @defer (on idle) {
    <app-newsletter-signup />
  } @placeholder {
    <div class="newsletter-placeholder"></div>
  }
</div>

Performance Benefits

  1. Smaller initial bundle — Deferred components are separate chunks
  2. Faster initial paint — Only essential content loads first
  3. Bandwidth savings — Heavy components download only when needed
  4. Better Core Web Vitals — Improved LCP and INP

Quiz

1. What does @defer do?

Question 1 options

2. Which trigger loads content when it enters the viewport?

Question 2 options

3. What is the default trigger for @defer?

Question 3 options

Flashcards

Question

What does @defer do?

Answer

Loads template content only when a trigger fires. Reduces initial bundle size.

Question

Which trigger for viewport loading?

Answer

on viewport — uses Intersection Observer.

Question

What is the default @defer trigger?

Answer

on idle — loads when browser is idle.

Revision Notes

Key Takeaways

  • 1. @defer loads content only when a trigger fires
  • 2. Triggers: idle, viewport, interaction, hover, timer, immediate
  • 3. Placeholder, loading, and error blocks handle all states
  • 4. Reduces initial bundle size and improves Core Web Vitals

Interview Tips

  • • Explain the performance benefits of deferred loading
  • • Be ready to describe each trigger type
  • • Mention Core Web Vitals improvements

Cheat Sheet

@defer Cheat Sheet

Basic:

@defer {
  <app-heavy />
} @placeholder {
  <p>Loading...</p>
}

Triggers:

  • on idle (default)
  • on viewport
  • on interaction
  • on hover
  • on timer(5s)
  • on immediate

Blocks:

  • @placeholder — before trigger
  • @loading — while downloading
  • @error — on failure

Continue Learning

Before You Start

Next Topics

Related Reading