Skip to content

Lab 19: Deferrable Views

step-18-album-wholesale-v21-post-signal-form

In this lab, you’ll implement lazy loading for components using Angular’s @defer blocks. You’ll convert conditional rendering with @if to use @defer with interaction triggers, add loading and placeholder states, and optimize bundle size by code-splitting heavy components.

Convert the comments component from conditional rendering to lazy loading.

Before (step-18):

@if (showComments()) {
<app-comments [albumId]="data.album.id"></app-comments>
}
@else {
<a class="primary" (click)="showComments.set(true)">Charger les commentaires</a>
}

After (step-19):

@defer (on interaction) {
<app-comments [albumId]="data.album.id"></app-comments>
} @placeholder {
<a class="primary">Charger les commentaires</a>
} @loading {
<p>Chargement des commentaires…</p>
} @error {
<p>Impossible de charger les commentaires.</p>
}

Since @defer handles the state, remove the showComments signal from the component:

export class DetailComponent {
// ❌ Remove this - no longer needed
// showComments = signal(false);
albumCommentsService = inject(AlbumCommentsService);
constructor(@Inject(MAT_DIALOG_DATA) public data: {album: Album}) {}
}

Clean up unused imports from the component:

// Before
imports: [CdkScrollable, MatDialogContent, ...]
// After
imports: [MatDialogContent, MatDialogTitle, ...]
  1. Run the application: npm start
  2. Open browser DevTools Network tab
  3. Open an album detail dialog
  4. Notice the comments component is NOT loaded initially
  5. Click “Charger les commentaires”
  6. Observe the lazy chunk being loaded in Network tab

Prevent loading flash on fast connections:

@defer (on interaction) {
<app-comments [albumId]="data.album.id"></app-comments>
} @loading (after 200ms; minimum 1s) {
<p>Chargement des commentaires…</p>
} @placeholder {
<a class="primary">Charger les commentaires</a>
}

Prefetch the component when browser is idle:

@defer (on interaction; prefetch on idle) {
<app-comments [albumId]="data.album.id"></app-comments>
} @placeholder {
<a class="primary">Charger les commentaires</a>
}
  • Comments component uses @defer (on interaction)
  • @placeholder, @loading, and @error blocks are implemented
  • showComments signal is removed
  • Unused imports are cleaned up
  • Component lazy loads only when user clicks
  • Bundle analysis shows separate chunk for comments component
Feature @if @defer
Bundle Included in main Separate chunk
Load timing On component init On trigger
State management Manual (signal) Automatic
Loading states Manual Built-in
Error handling Manual Built-in (@error)