• 23.08.2026 09:19:49
  • İbrahim Gökyar

Web programlama eğitimi kapsamında, CPU yoğun istemci kodunu Web Worker'a taşıyıp Long Task, geciken etkileşim ve bellek kopyalama maliyetlerini DevTools ve gerçek kullanıcı ölçümleriyle yönetmeyi inceleyin.

Web Programlama Eğitimi: Ana İş Parçacığını Web Workers ile Korumak

Web Programlama Eğitimi: Önce Long Task Kaynağını Kanıtlayın

Bir frontend development eğitimi projesinde "hesaplama yavaş" gözlemi yeterli değildir: Chrome DevTools Performance panelinde 4× CPU throttling ile kullanıcı akışını kaydedin, Main track üzerindeki 50 ms üstü sarı task'ları açın ve Bottom-up görünümünde self time'a göre sıralayın. Örneğin filtre yazarken her tuşta çalışan Array.sort(), JSON ayrıştırma veya istemci tarafı şifreleme aynı task içinde style/layout çalışmasını da geciktirebilir. Long Task API ile üretimde hangi route'un sorun ürettiğini ölçülebilir biçimde kaydedin.

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    navigator.sendBeacon('/rum/long-task', JSON.stringify({
      route: location.pathname,
      duration: Math.round(entry.duration),
      start: Math.round(entry.startTime)
    }));
  }
});
observer.observe({ type: 'longtask', buffered: true });

Karşılaştırmayı aynı veri kümesiyle yapın: örneğin 20.000 ürün, 10 ardışık filtre değişimi ve Chrome Performance kaydında en yüksek main-thread task süresi. Worker öncesi 280 ms, sonrası 18 ms gibi iki ölçümü saklayın; yalnızca toplam süreye bakmayın. Worker toplam CPU süresini azaltmaz, JavaScript yürütmesini ayrı bir thread'e taşır; ana thread'in input event, render ve paint kuyruğunu boşaltmasının nedeni budur. PerformanceObserver bazı gizlilik ve platform kısıtları nedeniyle attribution vermeyebilir; call stack için DevTools kaydı hâlâ gereklidir.

JavaScript Eğitimi İçin Doğru Worker Protokolü: Kopya mı Transfer mi?

javascript eğitimi içinde kritik ayrım, postMessage'ın structured clone kullanmasıdır. Büyük bir ArrayBuffer'ı clone etmek hem bellek hem CPU harcar; ikinci argümanda transfer listesi verirseniz buffer sahipliği worker'a geçer ve gönderen tarafta byteLength sıfırlanır. Bu, 8 MB'lık ikili veriyi filtreleme veya görsel ön işleme için taşırken gereksiz kopyayı önler; ancak gönderimden sonra aynı buffer'ı UI tarafında okumaya çalışan kod hata üretir.

// metrics.worker.js
self.onmessage = ({ data }) => {
  const { requestId, buffer } = data;
  const values = new Float32Array(buffer);
  values.sort();
  self.postMessage(
    { requestId, buffer: values.buffer },
    [values.buffer]
  );
};

// ui.js
const worker = new Worker(new URL('./metrics.worker.js', import.meta.url), {
  type: 'module'
});
const input = new Float32Array([3.2, 1.1, 2.4]);
worker.postMessage({ requestId: crypto.randomUUID(), buffer: input.buffer }, [input.buffer]);
// input.byteLength artık 0: buffer transfer edildi.

Worker mesajlarını bir RPC çağrısı gibi tasarlarken mutlaka requestId ve iptal stratejisi ekleyin. Kullanıcı "a", "ab", "abc" yazdığında üç filtre sonucu sırayla dönmek zorunda değildir; eski sonuç geç gelirse yeni UI state'ini ezebilir. AbortController worker içindeki saf CPU döngüsünü doğrudan durdurmaz; worker'a iptal mesajı gönderip uzun döngüde periyodik kontrol yapın veya her arama için worker'ı sonlandırıp yeniden oluşturmanın başlangıç maliyetini profil ile doğrulayın. Fonksiyonlar, DOM node'ları ve çoğu sınıf örneği structured clone edilemez; mesaj şemasını düz veri, typed array ve açık sürüm alanlarıyla sınırlamak bu edge case'i önler.

ReactJS Eğitimi, Angular Eğitimi ve VueJS Eğitimi ile Worker Entegrasyonu

reactjs eğitimi tarafında worker örneğini render fonksiyonunda yaratmayın; React Strict Mode geliştirme ortamında effect'leri tekrar çalıştırabildiği için iki worker ve çift event listener oluşabilir. Worker'ı useEffect içinde başlatın, cleanup'ta terminate() çağırın ve mesaj sonucunu request sırası ile doğrulayın.

function useSearchWorker() {
  const workerRef = React.useRef(null);
  const sequence = React.useRef(0);

  React.useEffect(() => {
    const worker = new Worker(new URL('./search.worker.js', import.meta.url), { type: 'module' });
    workerRef.current = worker;
    return () => worker.terminate();
  }, []);

  return (query, items) => new Promise((resolve) => {
    const id = ++sequence.current;
    const worker = workerRef.current;
    const onMessage = ({ data }) => {
      if (data.id === id) {
        worker.removeEventListener('message', onMessage);
        resolve(data.matches);
      }
    };
    worker.addEventListener('message', onMessage);
    worker.postMessage({ id, query, items });
  });
}

angular eğitimi projelerinde Angular CLI ile ng generate web-worker search komutu worker giriş dosyasını ve TypeScript yapılandırmasını oluşturur; worker mesajını NgZone.runOutsideAngular() içinde dinlemek, her ara ilerleme mesajında global change detection tetiklenmesini engeller. vuejs eğitimi için Vite'ın new Worker(new URL('./search.worker.ts', import.meta.url), { type: 'module' }) kalıbı statik analiz edilebilir URL sağlar; string ile dinamik dosya yolu vermek production bundle'ında asset çözümlemesini bozabilir. Eski bir angularjs eğitimi kod tabanında ise $scope.$applyAsync() yalnızca son worker sonucunda çağrılmalıdır; her progress mesajında $digest çalıştırmak ana thread kazanımını geri alır.

Frontend Framework Karşılaştırması Yerine İş Yükünü Sınıflandırın

Bir frontend framework karşılaştırması yaparken "React mi Angular mı daha hızlı?" sorusundan önce iş yükünü ayırın: DOM mutasyonu ve layout ana thread'de kalır; saf CPU hesapları worker'a uygundur; ağ I/O ise çoğunlukla async API ile zaten ana thread'i bloklamaz. Canvas tabanlı yoğun çizim için HTMLCanvasElement.transferControlToOffscreen() ve OffscreenCanvas kullanımı, hem hesaplamayı hem çizim komutlarını worker'a alabilir. Bunun için hedef tarayıcı matrisini BrowserStack veya gerçek cihaz testleriyle kontrol edin; destek yoksa ana thread canvas fallback'i ve frame bütçesi gerekir.

Worker'a taşınamayacak, ancak 10-20 ms parçalara bölünebilecek CPU işi için scheduler.postTask mevcut olduğunda kullanıcı etkileşimine öncelik verin; API yoksa setTimeout fallback'i uygulayın. requestIdleCallback kritik kullanıcı sonucu üretmek için güvenilir değildir: sürekli input veya animasyon altında callback uzun süre hiç çalışmayabilir.

const yieldToBrowser = () =>
  globalThis.scheduler?.postTask
    ? scheduler.postTask(() => {}, { priority: 'user-visible' })
    : new Promise(resolve => setTimeout(resolve, 0));

async function indexInChunks(records, onProgress) {
  const index = new Map();
  for (let i = 0; i < records.length; i++) {
    index.set(records[i].sku, records[i]);
    if (i % 500 === 0) {
      onProgress(i / records.length);
      await yieldToBrowser();
    }
  }
  return index;
}

Önce-Sonra Doğrulaması: DevTools, Playwright ve Bellek Profili

Değişikliği PR kabul kriterine bağlayın: Chrome DevTools Performance'da aynı cihaz emülasyonu ve aynı fixture ile main-thread en uzun task'ı, worker'a giden mesaj boyutunu ve heap kullanımını kaydedin. Memory panelindeki Heap Snapshot ile worker kapatıldıktan sonra MessagePort, büyük dizi veya closure'ın tutulmadığını kontrol edin. Worker yaşam döngüsü route değişiminde sonlandırılmazsa SPA sekmesi açık kaldıkça ayrı heap büyümeye devam eder.

CI'da Playwright ile kritik etkileşimin tamamlandığını tekrar edilebilir biçimde test edebilirsiniz; bu test doğrudan INP üretmez, fakat worker sonucu gelmeden UI'ın "hazır" durumuna geçtiği yarış koşullarını yakalar. RUM verisinde Long Task sayısı ve P75 etkileşim gecikmesini deploy öncesi/sonrası aynı route, cihaz sınıfı ve trafik segmentinde kıyaslayın; farklı kampanya trafiğini karşılaştırmaya katmak yanlış nedensellik üretir.

import { test, expect } from '@playwright/test';

test('20k kayıtta filtre sonucu güncel istekten gelir', async ({ page }) => {
  await page.goto('/catalog?fixture=20000');
  await page.getByLabel('Ara').fill('lap');
  await page.getByLabel('Ara').fill('laptop');
  await expect(page.getByTestId('result-count')).toHaveText('842');
  await expect(page.getByTestId('worker-status')).toHaveText('idle');
});

Sık Sorulan Sorular

Web programlama eğitimi kapsamında Web Worker ne zaman kullanılmalı?

Chrome DevTools Performance kaydında saf JavaScript hesaplaması 50 ms üstü task üretiyorsa adaydır. DOM erişimi, layout ölçümü ve çoğu UI kütüphanesi worker içinde çalışmaz; filtreleme, sıkıştırma, parser ve typed-array işlemlerini mesaj tabanlı bir modüle ayırın.

ReactJS eğitimi projelerinde Comlink kullanmak mantıklı mı?

Comlink, postMessage protokolünü Promise tabanlı API'ye çevirir ve karmaşık worker yüzeylerinde hata olasılığını azaltır. Ancak büyük ArrayBuffer gönderirken Comlink çağrısında transfer handler kullanın; aksi halde structured clone nedeniyle kopya maliyetini gizlemiş olursunuz. Basit tek yönlü filtre işlerinde açık requestId protokolü daha kolay denetlenir.

Angular eğitimi ve VueJS eğitimi için aynı worker dosyası paylaşılabilir mi?

Evet. Framework bağımsız çekirdeği yalnızca düz veri alan bir TypeScript modülü olarak yazın; Angular tarafında CLI worker girişi, Vue tarafında Vite module worker girişi oluşturun. UI framework'üne ait observable, ref veya component örneklerini mesajla göndermeyin; bunlar clone edilemez ya da anlamsız kopyalara dönüşür.

React Native eğitimi alan biri tarayıcı Web Worker bilgisini doğrudan kullanabilir mi?

Hayır. React Native'in JavaScript runtime'ı tarayıcı Worker API'sini standart olarak sunmaz; platforma göre JSI, native thread veya kullanılan kütüphanenin worker benzeri mekanizması gerekir. Paylaşılabilir kısım, mesaj şeması, iptal token'ı ve sıralı sonuç doğrulama tasarımıdır.

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