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β
- Run the application:
npm start - Open browser DevTools Network tab
- Open an album detail dialog
- Notice the comments component is NOT loaded initially
- Click "Charger les commentaires"
- 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@errorblocks are implementedshowCommentssignal 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 |
|---|---|---|
| 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) |