Angular @defer 2026: Daha Hızlı Uygulamalar için Bildirimsel Lazy Loading

Angular @defer bloklarında ustalaşın: bildirimsel lazy loading. Tetikleyiciler, prefetching, artımlı hidrasyon, SSR davranışı ve gerçek dünya performans kalıplarına derinlemesine bakış.

Angular defer loading ve lazy loading performans optimizasyonu

Angular @defer blokları, router tabanlı lazy loading'in hiçbir zaman çözemediği bir sorunu çözer: uygulamayı ayrı route'lara bölmeden bağımsız bileşenleri, direktifleri ve pipe'ları talep üzerine yükleme. Angular 17'de tanıtılan ve Angular 22 boyunca kararlı hale gelen @defer, eskiden dinamik import'lar, *ngIf bayrakları ve webpack yapılandırması gerektiren işi tek bir bildirimsel template bloğuna dönüştürür.

@defer ne yapar

@defer, Angular derleyicisine sarmalanan bileşenleri ayrı JavaScript parçalarına (chunk) bölmesini ve yalnızca bir tetikleyici koşulu gerçekleştiğinde yüklemesini söyler. Tarayıcı başlangıçta daha az JavaScript indirir; bu da manuel code-splitting yapılandırması olmadan Largest Contentful Paint (LCP) ve Time to First Byte (TTFB) değerlerini iyileştirir.

@defer Perde Arkasında Nasıl Çalışır

Angular derleyicisi bir @defer bloğuyla karşılaştığında, blok içindeki her bağımsız (standalone) bileşeni, direktifi ve pipe'ı ayrı bir parçaya çıkarır. Ana paket bu bağımlılıklar olmadan gönderilir. Çalışma zamanında Angular tetikleyici koşulunu değerlendirir ve parçayı dinamik bir import() çağrısıyla getirir.

Blok, yükleme yaşam döngüsü sırasında kullanıcının ne gördüğünü kontrol eden dört alt blok destekler:

app.component.htmltypescript
@defer (on viewport) {
  <analytics-dashboard />
} @placeholder {
  <div class="h-64 bg-muted animate-pulse"></div>
} @loading (minimum 200ms) {
  <loading-spinner />
} @error {
  <p>Failed to load the dashboard. Please refresh.</p>
}

@placeholder tetikleyici gerçekleşmeden önce render edilir. @loading parça indirilirken görünür ve titremeyi (flicker) önlemek için isteğe bağlı bir minimum süresi alır. @error ağ hatalarını veya parça hatalarını yakalar. @loading üzerindeki minimum parametresi, parça önbellekten hızlıca yüklendiğinde spinner'ın anlık parlamasını önler.

Bir kısıt: @defer içindeki her bağımlılık standalone olmalıdır. Bir NgModule içinde tanımlanan, standalone olmayan bileşenler ertelenemez ve @defer sarmalayıcısına bakılmaksızın hevesle (eagerly) yüklenir.

Tetikleyici Türleri: Bileşenlerin Ne Zaman Yükleneceğini Kontrol Etme

Angular, her biri farklı bir yükleme stratejisini hedefleyen yedi yerleşik tetikleyici sağlar. Birden fazla tetikleyici noktalı virgülle birleştirilebilir ve OR koşulu olarak değerlendirilir.

product-page.component.htmltypescript
// Loads when the browser goes idle (default)
@defer {
  <recommendation-engine />
}

// Loads when the element enters the viewport
@defer (on viewport) {
  <customer-reviews [productId]="product.id" />
}

// Loads on click or keydown
@defer (on interaction) {
  <product-configurator />
} @placeholder {
  <button>Configure this product</button>
}

// Loads on mouseenter or focusin
@defer (on hover) {
  <quick-preview />
}

// Loads after 3 seconds
@defer (on timer(3s)) {
  <chat-widget />
}

// Loads immediately after initial render
@defer (on immediate) {
  <notification-center />
}

on viewport tetikleyicisi dahili olarak Intersection Observer API kullanır. on idle tetikleyicisi requestIdleCallback'e devreder; bu da onu ekranın altındaki (below-the-fold) içerik için en güvenli varsayılan haline getirir. on timer tetikleyicisi süreleri milisaniye (500ms) veya saniye (3s) cinsinden kabul eder.

Reaktif Koşullar için when Tetikleyicisi

Olay tabanlı tetikleyicilerin ötesinde, when signal okumaları dahil herhangi bir boolean ifadeyi kabul eder:

dashboard.component.tstypescript
export class DashboardComponent {
  showAdvanced = signal(false);
}

// dashboard.component.html
@defer (when showAdvanced()) {
  <advanced-analytics />
} @placeholder {
  <button (click)="showAdvanced.set(true)">Show advanced analytics</button>
}

on ve when birleştirmek geçerlidir. Angular bunları OR olarak ele alır: blok, koşullardan herhangi biri karşılandığında yüklenir.

Prefetching: İndirmeyi Görüntülemeden Ayırma

Prefetching, parçanın ne zaman indirileceğini bileşenin ne zaman render edileceğinden ayırır. Bu, JavaScript'i kullanıcı tetiklemeden önce getirerek algılanan gecikmeyi ortadan kaldırır.

settings.component.htmltypescript
@defer (on interaction; prefetch on idle) {
  <account-settings />
} @placeholder {
  <button>Open settings</button>
}

Bu kalıpta tarayıcı account-settings parçasını boşta (idle) kalma süresi boyunca indirir. Kullanıcı tıkladığında bileşen anında render edilir, çünkü kod zaten mevcuttur. Prefetching, ana on ifadesiyle aynı tetikleyici türlerini kabul eder.

Dashboard'lar için yaygın bir kalıp: ağır bileşenleri boşta prefetch ederken render'ı viewport girişine ertelemek.

analytics.component.htmltypescript
@defer (on viewport; prefetch on idle) {
  <chart-widget [data]="salesData()" />
} @placeholder (minimum 100ms) {
  <div class="h-48 bg-muted rounded-none"></div>
}

@placeholder üzerindeki minimum, kullanıcı hızlıca kaydırdığında ve ertelenen bileşen neredeyse anında yüklendiğinde layout titremesini önler.

Angular mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

@defer ve Sunucu Tarafı Render (SSR)

Sunucuda @defer blokları varsayılan olarak @placeholder içeriğini render eder. Ertelenen bileşen hiçbir zaman sunucuda render edilmez. Bu davranış kasıtlıdır: parça indirmesi yalnızca tarayıcı bağlamında anlamlıdır.

SEO açısından kritik içerik için bu, @placeholder'ın yalnızca bir spinner değil, anlamlı HTML içermesi gerektiği anlamına gelir:

blog-post.component.htmltypescript
@defer (on viewport) {
  <comment-section [postId]="post.id" />
} @placeholder {
  <section aria-label="Comments">
    <h2>Comments</h2>
    <p>Loading comments...</p>
  </section>
}

Arama motorları SSR sırasında placeholder içeriğini indeksler. Açıklayıcı bir placeholder, sayfanın anlamsal olarak eksiksiz kalmasını sağlar.

@defer ile Artımlı Hidrasyon (Incremental Hydration)

Angular 19, geliştirici önizlemesinde artımlı hidrasyonu tanıttı ve Angular 22 bunu üretime hazır bir özellik olarak kararlı hale getirir. Artımlı hidrasyon, @defer'i sunucuda render edilen bir bileşenin istemcide ne zaman etkileşimli hale geleceğini kontrol eden bir hydrate tetikleyicisiyle genişletir.

product-page.component.htmltypescript
@defer (hydrate on viewport) {
  <product-gallery [images]="product.images" />
}

@defer (hydrate on interaction) {
  <product-reviews [productId]="product.id" />
}

Standart @defer'in aksine, artımlı hidrasyon tam bileşen HTML'ini sunucuda render eder. İstemci eksiksiz işaretlemeyi (markup) alır ancak tetikleyici gerçekleşene kadar bileşeni hidre etmeyi atlar. Sonuç: tarayıcı tam sayfayı hemen boyar, ancak JavaScript yürütmesi ertelenir.

Angular ekibi, içerik açısından yoğun sayfalarda artımlı hidrasyon kullanıldığında LCP skorlarında tutarlı %40-50'lik iyileşmeler bildiriyor. Sürüm 22'deki Angular DevTools, hidrasyon durumlarını (beklemede, hidre edilmiş, hata) doğrudan bileşen denetçisinde görselleştirir.

Gerçek Dünya Kalıpları ve Performans Stratejisi

Kalıp 1: Birden Fazla Ertelenmiş Panelli Ağır Dashboard

dashboard.component.htmltypescript
<div class="grid grid-cols-2 gap-4">
  @defer (on viewport; prefetch on idle) {
    <sales-chart />
  } @placeholder {
    <skeleton-card height="300px" />
  }

  @defer (on viewport; prefetch on idle) {
    <user-activity-feed />
  } @placeholder {
    <skeleton-card height="300px" />
  }

  @defer (on interaction) {
    <export-panel />
  } @placeholder {
    <button>Export data</button>
  }
</div>

Her panel bağımsız olarak yüklenir. Export paneli, kullanıcı açıkça talep edene kadar yüklenmez; bu da hiçbir zaman dışa aktarmayan kullanıcılar için tam bir parça indirmesinden tasarruf sağlar.

Kalıp 2: Signal'larla Koşullu Özellik Yükleme

editor.component.tstypescript
export class EditorComponent {
  user = inject(UserService).currentUser;
  isPremium = computed(() => this.user()?.plan === 'premium');
}

// editor.component.html
@defer (when isPremium()) {
  <ai-assistant />
} @placeholder {
  <upgrade-banner />
}

Ücretsiz katman kullanıcıları AI asistan parçasını hiçbir zaman indirmez. Yükseltme afişi (upgrade banner) hem placeholder hem de dönüşüm istemi olarak hizmet eder.

Yaygın Tuzaklardan Kaçınma

@defer bloklarını aynı tetikleyiciyle iç içe yerleştirmek, eşzamanlı parça indirmelerine neden olur. İç içe bloklarda tetikleyicileri kademelendirin:

typescript
// Avoid: both fire on idle simultaneously
@defer {
  @defer {
    <nested-heavy-component />
  }
}

// Better: outer on idle, inner on viewport
@defer (on idle) {
  <wrapper-component />
}
// Inside wrapper-component template:
@defer (on viewport) {
  <nested-heavy-component />
}

Başka bir tuzak: kritik render yolunda zaten bulunan bileşenler için @defer kullanmak. Ekranın üstündeki (above-the-fold) içeriği ertelemek LCP'yi artırır, çünkü tarayıcının boyama yapmadan önce parçayı indirmesi ve yürütmesi gerekir. @defer'i ekranın altındaki veya kullanıcı tetiklemeli içerik için saklayın.

@defer ile Router Tabanlı Lazy Loading Karşılaştırması

Router tabanlı lazy loading ve @defer birbirini tamamlar. Router lazy loading route düzeyinde bölerek tüm özellik modüllerini erteler. @defer bir template içinde bölerek bağımsız bileşenleri erteler.

| Yön | Router Lazy Loading | @defer | |--------|-------------------|--------| | Granülerlik | Route düzeyi | Bileşen düzeyi | | Tetikleyici | Gezinme olayı | viewport, idle, interaction, hover, timer, koşul | | SSR davranışı | Tam sunucu render | Sunucuda placeholder | | Standalone gerektirir | Hayır (NgModule'lerle çalışır) | Evet (yalnızca standalone) | | Prefetching | preloadingStrategy | prefetch on ifadesi | | Kullanım durumu | Özellik modülleri, sayfalar | Widget'lar, paneller, koşullu UI |

Tipik bir uygulama her ikisini de kullanır: üst düzey özellik alanları için router lazy loading ve bu alanlardaki ağır bileşenler için @defer.

Angular @defer Üzerine Mülakat Soruları

Teknik mülakatlar, Angular performans stratejisinin merkezinde yer almaya başladıkça @defer'i giderek daha fazla kapsıyor. İşte Angular mülakat sorularında yaygın olarak karşılaşılan kalıplar.

S: Standalone olmayan bir bileşen @defer içine yerleştirilirse ne olur? Bileşen, @defer bloğuna bakılmaksızın hevesle yüklenir. Angular derleyicisi, NgModule'de tanımlanan bileşenleri ayrı parçalara çıkaramaz. Hata fırlatılmaz, ancak optimizasyon sessizce başarısız olur.

S: @defer SSR sırasında nasıl davranır? Sunucu @placeholder içeriğini render eder. Ertelenen bileşen hiçbir zaman sunucu tarafında render edilmez. Hidrasyon, tetikleyici gerçekleştiğinde istemcide gerçekleşir (veya artımlı hidrasyon için hydrate on aracılığıyla).

S: @defer OnPush change detection ile kullanılabilir mi? Evet. @defer bir template düzeyi özelliğidir ve herhangi bir change detection stratejisiyle çalışır. Ertelenen bileşen, yüklendikten sonra kendi change detection yapılandırmasını izler.

S: on idle ile on immediate arasındaki fark nedir? on idle, tarayıcının requestIdleCallback aracılığıyla bekleyen tüm işleri bitirmesini bekler. on immediate, boşta durumunu beklemeden Angular ilk render geçişini tamamladıktan hemen sonra tetiklenir. on immediate, yakında yüklenmesi gereken ancak ilk boyamayı engellememesi gereken bileşenler için kullanışlıdır.

Daha geniş bir Angular mülakat hazırlığı seti için Angular change detection modülüne ve Angular signals modülüne bakın.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Sonuç

  • @defer, standalone bileşenleri talep üzerine yüklenen ayrı parçalara böler ve route yeniden yapılandırması olmadan başlangıç paket boyutunu azaltır
  • Yedi tetikleyici türü (idle, viewport, interaction, hover, timer, immediate, when) pasiften kullanıcı odaklıya kadar her yükleme stratejisini kapsar
  • prefetch on, parça indirmesini bileşen render'ından ayırarak kullanıcı tetiklemeli bileşenlerde algılanan gecikmeyi ortadan kaldırır
  • Artımlı hidrasyon (hydrate on), tam HTML'i sunucuda render ederken JavaScript yürütmesini istemciye erteler ve içerik açısından yoğun sayfalarda %40-50 LCP iyileşmesi sağlar
  • @placeholder içeriği SSR sırasında render edilir ve SEO için anlamsal olarak anlamlı olmalıdır
  • @defer, router tabanlı lazy loading'i tamamlar: özellik düzeyinde bölme için route'lar, template içinde bileşen düzeyinde bölme için @defer
  • Standalone olmayan bileşenler ertelenemez ve sessizce hevesle yüklenir

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Etiketler

#angular
#angular-defer
#lazy-loading
#performance
#ssr
#signals
#deep-dive

Paylaş

İlgili makaleler