# Angular @defer di 2026: Lazy Loading Deklaratif untuk Aplikasi Lebih Cepat > Blok @defer pada Angular memungkinkan lazy loading deklaratif dengan trigger viewport, interaction, dan timer. Panduan mendalam tentang prefetching, SSR, incremental hydration, dan pola optimasi performa. - Published: 2026-06-14 - Updated: 2026-06-14 - Author: SharpSkill - Tags: angular, performance, lazy-loading - Reading time: 8 min --- Blok `@defer` pada Angular menyelesaikan permasalahan yang tidak pernah mampu dijangkau oleh lazy loading berbasis router: memuat komponen, directive, dan pipe secara individual sesuai kebutuhan tanpa harus merestrukturisasi aplikasi menjadi rute-rute terpisah. Diperkenalkan pada Angular 17 dan telah distabilkan hingga Angular 22, `@defer` mengubah proses yang sebelumnya memerlukan dynamic import, flag `*ngIf`, dan konfigurasi webpack menjadi satu blok template deklaratif. > **Fungsi @defer** > > `@defer` menginstruksikan compiler Angular untuk memecah komponen yang dibungkus ke dalam chunk JavaScript terpisah, yang hanya dimuat ketika kondisi trigger terpenuhi. Browser mengunduh lebih sedikit JavaScript pada pemuatan awal, sehingga memperbaiki skor Largest Contentful Paint (LCP) dan Time to First Byte (TTFB) tanpa memerlukan konfigurasi code-splitting secara manual. ## Cara Kerja Internal @defer Ketika compiler Angular menemukan blok `@defer`, seluruh standalone component, directive, dan pipe yang berada di dalamnya diekstrak ke dalam chunk terpisah. Bundle utama dikirimkan ke browser tanpa menyertakan dependensi tersebut. Pada saat runtime, Angular mengevaluasi kondisi trigger dan mengambil chunk melalui pemanggilan `import()` dinamis. Blok ini mendukung empat sub-blok yang mengontrol tampilan visual selama siklus pemuatan: ```typescript // app.component.html @defer (on viewport) { } @placeholder {
} @loading (minimum 200ms) { } @error {

Failed to load the dashboard. Please refresh.

} ``` Sub-blok `@placeholder` ditampilkan sebelum trigger aktif. Sub-blok `@loading` muncul selama proses pengunduhan chunk berlangsung, dengan parameter `minimum` opsional yang mencegah flicker. Sub-blok `@error` menangkap kegagalan jaringan atau kesalahan chunk. Parameter `minimum` pada `@loading` menghindari munculnya spinner secara sekilas ketika chunk sudah tersimpan di cache dan dimuat dengan cepat. Satu batasan yang perlu diperhatikan: setiap dependensi di dalam `@defer` wajib bersifat standalone. Komponen non-standalone yang dideklarasikan melalui `NgModule` tidak dapat di-defer dan akan dimuat secara eager terlepas dari pembungkus `@defer` yang digunakan. ## Tipe Trigger: Menentukan Kapan Komponen Dimuat Angular menyediakan tujuh trigger bawaan, masing-masing menargetkan strategi pemuatan yang berbeda. Beberapa trigger dapat digabungkan menggunakan tanda titik koma dan dievaluasi sebagai kondisi OR. ```typescript // product-page.component.html // Loads when the browser goes idle (default) @defer { } // Loads when the element enters the viewport @defer (on viewport) { } // Loads on click or keydown @defer (on interaction) { } @placeholder { } // Loads on mouseenter or focusin @defer (on hover) { } // Loads after 3 seconds @defer (on timer(3s)) { } // Loads immediately after initial render @defer (on immediate) { } ``` Trigger `on viewport` menggunakan Intersection Observer API secara internal. Trigger `on idle` mendelegasikan tugas ke `requestIdleCallback`, menjadikannya pilihan default paling aman untuk konten yang berada di bawah lipatan halaman. Trigger `on timer` menerima durasi dalam satuan milidetik (`500ms`) atau detik (`3s`). ### Trigger `when` untuk Kondisi Reaktif Selain trigger berbasis event, `when` menerima ekspresi boolean apa pun, termasuk pembacaan signal: ```typescript // dashboard.component.ts export class DashboardComponent { showAdvanced = signal(false); } // dashboard.component.html @defer (when showAdvanced()) { } @placeholder { } ``` Menggabungkan `on` dan `when` dalam satu blok adalah hal yang valid. Angular memperlakukan keduanya sebagai OR: blok dimuat ketika salah satu kondisi terpenuhi terlebih dahulu. ## Prefetching: Memisahkan Pengunduhan dari Penampilan Prefetching memisahkan waktu pengunduhan chunk dari waktu komponen ditampilkan. Mekanisme ini menghilangkan latensi yang dirasakan pengguna dengan mengambil JavaScript sebelum trigger utama aktif. ```typescript // settings.component.html @defer (on interaction; prefetch on idle) { } @placeholder { } ``` Pada pola ini, browser mengunduh chunk `account-settings` selama waktu idle. Ketika pengguna mengklik tombol, komponen langsung ditampilkan karena kode sudah tersedia di memori. Klausa `prefetch on` menerima tipe trigger yang sama dengan klausa `on` utama. Pola yang lazim digunakan pada halaman dashboard: melakukan prefetch komponen berat saat idle sambil menunda rendering hingga elemen memasuki viewport. ```typescript // analytics.component.html @defer (on viewport; prefetch on idle) { } @placeholder (minimum 100ms) {
} ``` ## @defer dan Server-Side Rendering Pada sisi server, blok `@defer` hanya merender konten `@placeholder` secara default. Komponen yang di-defer tidak pernah diproses di server. Perilaku ini disengaja karena pengunduhan chunk hanya relevan dalam konteks browser. Untuk konten yang kritis bagi SEO, hal ini berarti `@placeholder` harus berisi HTML yang bermakna secara semantik, bukan sekadar spinner: ```typescript // blog-post.component.html @defer (on viewport) { } @placeholder {

Comments

Loading comments...

} ``` Mesin pencari mengindeks konten placeholder selama proses SSR. Placeholder yang deskriptif dan terstruktur dengan baik menjamin bahwa halaman tetap memiliki kelengkapan semantik yang dibutuhkan untuk peringkat pencarian yang optimal. ## Incremental Hydration dengan @defer Angular 19 memperkenalkan incremental hydration dalam tahap developer preview, dan Angular 22 telah menstabilkannya sebagai fitur yang siap produksi. Incremental hydration memperluas kemampuan `@defer` dengan trigger `hydrate` yang mengontrol kapan sebuah komponen yang sudah dirender di server menjadi interaktif di sisi klien. ```typescript // product-page.component.html @defer (hydrate on viewport) { } @defer (hydrate on interaction) { } ``` Berbeda dengan `@defer` standar, incremental hydration merender HTML lengkap komponen di sisi server. Klien menerima markup yang utuh tetapi melewati proses hydration komponen hingga trigger aktif. Hasilnya: browser menampilkan seluruh halaman secara langsung, sementara eksekusi JavaScript ditunda sesuai kebutuhan. Tim Angular melaporkan peningkatan konsisten sebesar 40-50% pada skor LCP ketika incremental hydration diterapkan pada halaman dengan konten yang padat. Angular DevTools versi 22 menyediakan visualisasi status hydration (pending, hydrated, error) langsung di component inspector. ## Pola Dunia Nyata dan Strategi Performa ### Pola 1: Dashboard Berat dengan Beberapa Panel yang Di-defer ```typescript // dashboard.component.html
@defer (on viewport; prefetch on idle) { } @placeholder { } @defer (on viewport; prefetch on idle) { } @placeholder { } @defer (on interaction) { } @placeholder { }
``` Setiap panel dimuat secara independen. Panel grafik penjualan dan feed aktivitas dimuat ketika terlihat di viewport, sedangkan panel ekspor tetap tidak dimuat hingga pengguna secara eksplisit mengklik tombol. Pengguna yang tidak pernah melakukan ekspor data sama sekali tidak perlu mengunduh chunk yang terkait, sehingga menghemat bandwidth secara signifikan. ### Pola 2: Pemuatan Fitur Bersyarat dengan Signal ```typescript // editor.component.ts export class EditorComponent { user = inject(UserService).currentUser; isPremium = computed(() => this.user()?.plan === 'premium'); } // editor.component.html @defer (when isPremium()) { } @placeholder { } ``` Pengguna pada paket gratis tidak akan mengunduh chunk AI assistant sama sekali. Banner upgrade yang menjadi placeholder berfungsi ganda sebagai indikator visual sekaligus elemen konversi yang mendorong peningkatan langganan. ### Menghindari Kesalahan Umum Menempatkan blok `@defer` bersarang dengan trigger yang identik menyebabkan pengunduhan chunk terjadi secara bersamaan, yang justru meniadakan manfaat lazy loading. Trigger pada blok bersarang sebaiknya dibedakan: ```typescript // Avoid: both fire on idle simultaneously @defer { @defer { } } // Better: outer on idle, inner on viewport @defer (on idle) { } // Inside wrapper-component template: @defer (on viewport) { } ``` Kesalahan lain yang sering terjadi adalah menerapkan `@defer` pada komponen yang berada di area atas halaman (above-the-fold). Tindakan ini justru meningkatkan LCP karena browser harus menunggu pengunduhan chunk tambahan sebelum dapat menampilkan konten utama. Blok `@defer` sebaiknya digunakan secara khusus untuk konten di bawah lipatan halaman atau konten yang muncul sebagai respons terhadap aksi pengguna. ## @defer vs Lazy Loading Berbasis Router Lazy loading berbasis router dan `@defer` saling melengkapi satu sama lain. Router lazy loading memecah kode pada level rute, menunda pemuatan seluruh feature module. `@defer` memecah kode di dalam template, menunda pemuatan komponen individual. | Aspect | Router Lazy Loading | @defer | |--------|-------------------|--------| | Granularity | Route level | Component level | | Trigger | Navigation event | viewport, idle, interaction, hover, timer, condition | | SSR behavior | Full server render | Placeholder on server | | Requires standalone | No (works with NgModules) | Yes (standalone only) | | Prefetching | `preloadingStrategy` | `prefetch on` clause | | Use case | Feature modules, pages | Widgets, panels, conditional UI | Arsitektur aplikasi yang paling optimal menerapkan keduanya secara berlapis: router lazy loading untuk memisahkan halaman-halaman utama (dashboard, pengaturan, laporan), dan `@defer` untuk memisahkan komponen berat di dalam setiap halaman tersebut (grafik, tabel data, editor teks kaya). ## Pertanyaan Interview Seputar Angular @defer Topik `@defer` semakin sering diujikan dalam sesi interview teknis seiring dengan meningkatnya peran fitur ini dalam strategi performa Angular. Berikut adalah pertanyaan-pertanyaan yang kerap muncul. **T: Apa yang terjadi apabila komponen non-standalone ditempatkan di dalam blok @defer?** Komponen tersebut dimuat secara eager tanpa memperhatikan blok `@defer` yang membungkusnya. Compiler Angular tidak mampu mengekstrak komponen yang dideklarasikan melalui NgModule ke dalam chunk terpisah. Tidak ada error yang dilemparkan, namun optimasi secara diam-diam gagal diterapkan. **T: Bagaimana perilaku @defer pada saat SSR?** Server hanya merender konten `@placeholder`. Komponen yang di-defer tidak pernah dirender di sisi server. Hydration terjadi di sisi klien ketika trigger aktif (atau melalui `hydrate on` untuk incremental hydration). **T: Apakah @defer dapat digunakan bersamaan dengan change detection OnPush?** Ya. `@defer` merupakan fitur pada level template dan kompatibel dengan strategi change detection mana pun. Komponen yang di-defer mengikuti konfigurasi change detection miliknya sendiri setelah berhasil dimuat. **T: Apa perbedaan antara `on idle` dan `on immediate`?** `on idle` menunggu browser menyelesaikan seluruh pekerjaan yang tertunda melalui `requestIdleCallback`. `on immediate` memicu pemuatan tepat setelah Angular menyelesaikan pass render awal, tanpa menunggu kondisi idle. Trigger `on immediate` cocok untuk komponen yang perlu segera tersedia tetapi tidak boleh menghalangi proses first paint. ## Kesimpulan - `@defer` memecah standalone components ke dalam chunk JavaScript terpisah yang dimuat sesuai kebutuhan, mengurangi ukuran bundle awal tanpa perlu merestrukturisasi rute aplikasi - Tujuh tipe trigger (`idle`, `viewport`, `interaction`, `hover`, `timer`, `immediate`, `when`) mencakup seluruh strategi pemuatan mulai dari pasif hingga yang dipicu oleh pengguna - Klausa `prefetch on` memisahkan pengunduhan chunk dari rendering komponen, menghilangkan latensi yang dirasakan pengguna saat berinteraksi dengan komponen yang di-defer - Incremental hydration (`hydrate on`) merender HTML lengkap di server sambil menunda eksekusi JavaScript di klien, menghasilkan peningkatan skor LCP sebesar 40-50% pada halaman yang padat konten - Konten `@placeholder` dirender selama SSR dan wajib bermakna secara semantik agar kualitas SEO tetap terjaga - `@defer` melengkapi lazy loading berbasis router: gunakan router untuk pemecahan kode pada level rute dan `@defer` untuk pemecahan kode pada level komponen di dalam template - Komponen non-standalone tidak dapat di-defer dan akan dimuat secara eager tanpa peringatan dari compiler --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/angular/angular-defer-loading-declarative-lazy-loading-guide