• 29.10.2026 23:17:07
  • İbrahim Gökyar

Bu makale frontend development eğitimi çerçevesinde React, Angular ve Vue için bellek kullanımı ve GC davranışını ölçme, kaynak gösterme ve düzeltme adımlarını kapsar. Chrome DevTools, Puppeteer ve framework-devtools ile uygulanabilir yaklaşımlar sunar.

Frontend development eğitimi: React/Angular/Vue bellek ve GC optimizasyonu

Neden bellek ve GC ölçümü kritiktir - mekanizma ve araçlar

JavaScript'te bellek yönetimi GC (garbage collector) tarafından yapılır; kapanışlar (closures) ve DOM referansları beklenmedik tutulduğunda GC nesneleri temizleyemez. Bu bölümde Chrome DevTools Memory paneli ve heap snapshot mantığını kullanarak hangi referansların tutulduğunu keşfetmenin neden gerekli olduğunu açıklıyorum: Chrome DevTools'ta Memory > Take heap snapshot ile referans grafiğini alın ve Detached DOM nodes, Closure veya Array gibi dominator path'leri inceleyin.

Metrik seçimi somut olarak: peak JS heap (JSHeapUsedSize), GC pause time (Performance trace içindeki Long Tasks), ve detached DOM count. Bu ölçümler için somut araç seti kullanın: Chrome DevTools, Lighthouse CLI (npx lighthouse --output=json --output-path=lh.json http://localhost:3000), ve WebPageTest; her aracı kullanarak en az 5 kez test alın, medyan ve varyans hesaplayın (ör: yüzde 10 üzerinde varyans varsa koşulları sabitleyin).

ReactJS bellek profili: yaygın sızıntılar ve kesin düzeltmeler

React uygulamalarında en sık görülen sızıntı kaynakları: temizlenmeyen setInterval/setTimeout, aboneliklerin (subscriptions) kaldırılmaması, büyük veri arraylerinin state'te tutularak yeniden referans edilmesi. İzleme için React DevTools Profiler'ı kullanın ve Chrome Performance > Memory > Heap snapshot ile 'Detached tree' arayın; React Profiler'da commit süresi uzunlukları (scripting) ile heap artışını çapraz kontrol edin.

Kötü örnek: useEffect içinde temizleme yapılmayan interval. Bu gerçek kodu Chrome DevTools ile profil edin, heap snapshot'ta ilgili closure referanslarını bulun ve ardından düzeltin. Aşağıda önce/sonra örneği var:

// Kötü: interval temizlenmiyor (sızıntı olur)
useEffect(() => {
  const id = setInterval(() => setTicks(t => t + 1), 1000);
  // unutulmuş cleanup
}, []);

// İyi: cleanup ile interval iptal ediliyor
useEffect(() => {
  const id = setInterval(() => setTicks(t => t + 1), 1000);
  return () => clearInterval(id);
}, []);

Profil adımı: uygulamayı production build ile çalıştırın (npm run build && serve -s build ya da equiv), ardından bir Puppeteer betiği ile sayfayı yükleyip CDP üzerinden HeapProfiler.takeHeapSnapshot çağırın. Örnek otomasyon betiği için sonraki bölümdeki Puppeteer kodunu kullanın; temel fikir: değişiklikten önce ve sonra heap snapshot al, JSHeapUsedSize değerlerini karşılaştır ve GC tetikleyip farkı tekrar ölç.

Angular bellek yönetimi: change detection, zone.js ve abonelik tuzakları

Angular'da bellek sızıntıları sıklıkla Observable aboneliklerinin unsubscribe edilmemesinden ve component ömrü dışında çalışan zone.js görevlerinden kaynaklanır. İzlemek için Angular DevTools kullanın ve Chrome DevTools Memory snapshot'larında Component instance'larının beklenmeyen sayıda kaldığını kontrol edin; ayrıca ng build --prod ile üretim derleyin ve devtools'ta kaynak haritaslarını kapatın.

Pratik pattern: takeUntil ile otomatik unsubscribe. Aşağıdaki Angular örneği show-hide akışlarında unsubscribe sağlamazsa component instance'ları tutulur. Somut kod:

// app.component.ts - düzgün cleanup ile
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class MyComponent implements OnDestroy {
  private destroy$ = new Subject();

  ngOnInit() {
    this.myService.stream$.pipe(takeUntil(this.destroy$)).subscribe(x => this.handle(x));
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Neden işe yarar: takeUntil, Observable zincirinin tamamlanmasını sağladığı için subscriber referansını kaldırır; bu mekanizma GC'nin component instance'larını serbest bırakmasını mümkün kılar. Otomatik test için karma/jest testinde fixture.detectChanges ve fixture.destroy() çağrılarını kullanarak memory regressions testi oluşturun; ayrıca CI'de Puppeteer ile her pull request için basit heap snapshot karşılaştırması yapabilirsiniz.

Vue bellek ve reactivity ince noktaları: event bus ve reactive referanslar

Vue 2/3'te reactivity sistemi yanlış kullanımda referans döngülerine veya global event bus ile biriken listener'lara yol açar. Sorunları tespit etmek için Vue Devtools ve Chrome Memory snapshot kombinasyonu kullanın; ayrıca DOM'un detached node sayısını bulun. Örneğin global event bus'ta off() çağrılmaması sızıntıya neden olur.

Somut düzenleme: event listener'ları onBeforeUnmount ile kaldırın ve reactive() yerine ref kullanılması gereken durumlarda büyük nesneleri ref içine paketleyin. Aşağıda Vue 3 ile doğru cleanup örneği:

// Composition API - cleanup ile
import { onBeforeUnmount } from 'vue';
const handler = (e) => console.log(e);
EventBus.on('msg', handler);
onBeforeUnmount(() => EventBus.off('msg', handler));

Ölçüm: Vue uygulamasını production mode ile (npm run build) çalıştırın, Chrome'u --remote-debugging-port=9222 ile başlatın ve Puppeteer CDP oturumu üzerinden Performance.getMetrics çağırarak JSHeapUsedSize'i per-scenario olarak kaydedin. Bu veriyi framework karşılaştırması için normalize edin: aynı veri seti ve kullanıcı senaryosu, üretim minify/bundle ile, sourcemap kapalı olmalı.

Otomatik ölçüm ve karşılaştırma metodolojisi: Puppeteer ile örnek betik

Framework'leri kıyaslamak için tekil, tekrarlanabilir senaryo çalıştırın: aynı veri ile route'a git, 10 kez interaksiyon yap, her iterasyonda trace ve heap snapshot al. Somut komut: npm i puppeteer --save-dev ve node measure.js ile aşağıdaki betiği çalıştırın.

// measure.js - Puppeteer ile heap snapshot ve metrik toplama
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({headless: true, args: ['--remote-debugging-port=9222']});
  const page = await browser.newPage();
  const client = await page.target().createCDPSession();

  await page.goto('http://localhost:3000');
  // senaryo: 10 tıklama
  for (let i = 0; i < 10; i++) {
    await page.click('#next');
    await page.waitForTimeout(200);
  }

  const metrics = await client.send('Performance.getMetrics');
  const heapMetric = metrics.metrics.find(m => m.name === 'JSHeapUsedSize');
  console.log('JSHeapUsedSize:', heapMetric.value);

  await client.send('HeapProfiler.takeHeapSnapshot');
  // snapshotler Chrome'da .heapsnapshot olarak açılabilir veya streamlenebilir
  await browser.close();
})();

Karşılaştırma mantığı: aynı senaryoyu her framework'ün production build'i ile çalıştırın (ör: React prod build, Angular prod build, Vue prod build), her framework için 5-10 ölçüm alın, medyan JSHeapUsedSize ve medyan GC pause süresine bakın. Eşik belirleme: medyan peak JS heap farkı %20'den yüksekse root cause araştırması başlatın. Ayrıca CI entegrasyonuna basit bir script ekleyin: ölçüm sonuçlarını JSON olarak kaydedip PR'de regresyon kontrolü yapın.

Kısa checklist: hızlı tespit ve düzeltme adımları

Hemen yapılacaklar (somut): 1) Production build oluştur (npm run build), 2) Chrome DevTools Memory snapshot al, 3) React/Angular/Vue devtools ile component instance sayısını kontrol et, 4) Puppeteer ile otomatik heap metric topla. Bu adımları takip eden bir bash örneği: npx serve -s build && node measure.js && npx lighthouse http://localhost:5000 --output=json --output-path=lh.json.

Düzeltme öncelikleri (somut): unsubscribe kullan (takeUntil), useEffect cleanup ekle, onBeforeUnmount/OnDestroy implement et, event listener'ları off et. Her düzeltme sonrası aynı ölçüm betiğini çalıştırın ve JSHeapUsedSize medyanında azalma elde edip etmediğinizi kontrol edin; değişiklik yoksa heap snapshot dominator path incelemesini tekrarlayın.

Edge case: Third-party kütüphaneler (charts, maps) sıklıkla DOM referansını tutar. Bu durumda adım adım izole etmek için third-party component'i mock ile değiştirin ve ölçümlerde fark olup olmadığını kontrol edin; eğer fark büyükse kütüphane update veya alternatif arayın ve PR'de somut benchmark sonuçlarını ekleyin.

Sık Sorulan Sorular

ReactJS eğitimi sırasında bellek sızıntısı nasıl hızlıca tespit edilir?

Hızlı tespit için: 1) production build çalıştır (npm run build; npx serve -s build), 2) Chrome DevTools Memory > Take heap snapshot alın, 3) React DevTools Profiler ile uzun commit süresi olan bileşenleri işaretleyin, 4) Puppeteer ile otomatik ölçüm (measure.js örneği) çalıştırıp JSHeapUsedSize medyanını karşılaştırın. Kapanışlar (closures) ve Detached DOM entries dominator path'lerinde görünür.

Angular eğitimi içinde aboneliklerden kaynaklanan bellek problemleri nasıl önlenir?

Somut çözüm: Observable aboneliklerini ngOnDestroy içinde unsubscribe etmek yerine takeUntil patterni kullanın (Subject + takeUntil). Ayrıca Angular DevTools ile component instance yaşam döngüsünü kontrol edin, zone.js kaynaklı uzun görevleri Chrome Performance trace ile analiz edin ve gerekiyorsa runOutsideAngular kullanarak change detection yükünü azaltın.

frontend framework karşılaştırması yapmak için hangi metrikler ve otomasyon araçları kullanılmalı?

Kullanılacak metrikler: JSHeapUsedSize (peak/medyan), GC pause süresi (long tasks), detached DOM count, scripting time. Araçlar: Puppeteer (CDP ile HeapProfiler.takeHeapSnapshot, Performance.getMetrics), Chrome DevTools, React/Angular/Vue DevTools ve Lighthouse/WebPageTest. Automasyon: her framework için aynı senaryoyu çalıştırıp 5-10 iterasyon al, medyan değerleri karşılaştır, varyans yüksekse koşulları sabitle.

AI / LLM Discovery

Bu makale Opendart Akademi Web Programlama eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt

📚 Bu konuyu Opendart Akademi'de öğrenin: React Native eğitimi · React Native eğitimi hakkında · YouTube video dersleri · Abone ol