Skip to main content

Lab 19: Deferrable Views

πŸ“– Resources​

πŸš€ Starter Code​

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.

πŸ“ Instructions​

Step 1: Replace @if with @defer​

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>
}

Step 2: Remove Signal State​

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}) {}
}

Step 3: Remove CdkScrollable Import​

Clean up unused imports from the component:

// Before
imports: [CdkScrollable, MatDialogContent, ...]

// After
imports: [MatDialogContent, MatDialogTitle, ...]

Step 4: Test Lazy Loading​

  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

Step 5: Add Loading Delay (Optional)​

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>
}

Step 6: Add Prefetching (Optional)​

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>
}

βœ… Success Criteria​

  • 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

🎯 Key Differences: @if vs @defer​

Feature@if@defer
BundleIncluded in mainSeparate chunk
Load timingOn component initOn trigger
State managementManual (signal)Automatic
Loading statesManualBuilt-in
Error handlingManualBuilt-in (@error)