INP Değerinin 200ms Altında Tutulması

SEOBAZ SEO 25 Nisan 2026
INP Değerinin 200ms Altında Tutulması
⚡ ÖZET

INP değerinin 200 ms altında tutulması, kullanıcı etkileşimlerinin input delay, processing time ve presentation delay fazlarının toplamının Google'ın belirlediği eşik altında kalmasını gerektiren Core Web Vitals standardıdır. Long task parçalama, Web Worker izolasyonu, React concurrent rendering, CSS containment ve virtualization bu standardın temel optimizasyon bileşenleridir.

🧠 Bu Rehberi 5 Farklı AI ile Test Et

Her modelin GEO karakterine göre özel prompt hazırlandı. Tıkla, kopyalansın ve ilgili AI açılsın.

INP (Interaction to Next Paint), kullanıcının sayfayla etkileşime geçtiği andan görsel güncellemenin ekrana yansıdığı ana kadar geçen süreyi ölçen Core Web Vitals metriğidir. 2026 itibarıyla Google, INP eşiğini 200 ms olarak belirlemiş olup bu değeri aşan sayfalar sıralama algoritmasında negatif sinyal üretmektedir. FID'in yerini alan bu metrik, sayfanın tüm yaşam döngüsü boyunca ölçüm yaptığı için etkileşim performansının gerçek ve kapsamlı göstergesidir.

INP ile FID Arasındaki Temel Fark

FID (First Input Delay), yalnızca kullanıcının sayfayla yaptığı ilk etkileşimin gecikme süresini ölçüyordu. Sayfa yüklendikten sonraki tüm etkileşimler FID kapsamı dışındaydı. INP ise sayfanın tüm yaşam döngüsü boyunca gerçekleşen her etkileşimi kaydeder ve en kötü performans gösteren etkileşimi (veya yüksek yüzdelik dilimi) raporlar.

Bu fark pratikte büyük sonuçlar doğurur. FID'de yalnızca ilk tıklama ölçüldüğü için, sayfa yüklendikten sonra ağırlaşan JavaScript görevleri görünmezdi. INP, kullanıcının üçüncü dakikada açtığı dropdown menüdeki gecikmeyi de yakalar. Dolayısıyla INP optimizasyonu, sayfa yükleme performansının ötesinde, runtime JavaScript performansının tamamını kapsar. Bu durum, optimizasyon stratejisini kökten değiştirir.

INP Ölçümünün Üç Fazı

INP süresi üç ardışık fazdan oluşur: input delay, processing time ve presentation delay. Input delay, kullanıcı etkileşiminin başladığı andan event handler'ın çalışmaya başladığı ana kadar geçen süredir. Bu süre, ana thread'in başka bir görevle meşgul olması nedeniyle oluşur. Processing time, event handler'ın çalışma süresidir. Presentation delay ise event handler tamamlandıktan sonra tarayıcının görsel güncellemeyi ekrana çizmesi için geçen süredir.

Bu üç fazı ayrı ayrı ölçmek, darboğazın nerede olduğunu tespit etmenin ön koşuludur. Chrome DevTools Performance sekmesinde bir etkileşimi yakaladığınızda, "Interactions" lane'inde her fazın süresini görebilirsiniz. Input delay yüksekse sorun long task'lardadır. Processing time yüksekse event handler'da ağır hesaplama vardır. Presentation delay yüksekse layout ve paint işlemleri optimize edilmelidir.

Input Delay ve Long Task Kavramı

Input delay, ana thread'in kullanıcı etkileşimini hemen işleyememesi durumunda oluşur. Ana thread, o anda 50 ms'yi aşan bir JavaScript görevi (long task) çalıştırıyorsa, kullanıcının tıklaması veya tuş basması bu görev tamamlanana kadar kuyrukta bekler. Bekleme süresi, input delay olarak INP'ye eklenir.

Long task'ların en yaygın kaynakları şunlardır: hydration süreci, üçüncü parti script yüklemeleri, büyük veri setlerinin parse edilmesi ve ağır DOM manipülasyonları. Chrome DevTools Performance sekmesinde Main thread timeline'ında kırmızı üçgenle işaretlenen bloklar long task'lardır. Bu blokların üzerine tıkladığınızda, hangi fonksiyonun ne kadar süre harcadığını görürsünüz. 50 ms'yi aşan her görev, potansiyel bir INP sorunu kaynağıdır.

Processing Time Optimizasyonu ve Event Handler Verimliliği

Event handler'ın çalışma süresi, INP'nin processing time fazını oluşturur. Bir butona tıklandığında çalışan fonksiyon 150 ms sürüyorsa, bu süre doğrudan INP'ye eklenir. Ağır hesaplamalar, büyük state güncellemeleri ve senkron DOM manipülasyonları bu fazın uzamasının başlıca nedenleridir.

Çözüm, event handler içindeki işlemleri minimumda tutmaktır. Ağır hesaplamaları Web Worker'a taşıyın. Büyük liste render'larını sanal liste (virtualization) ile optimize edin. State güncellemelerini batch'leyin. React 18'in startTransition API'si, düşük öncelikli güncellemeleri ana thread'i bloke etmeden gerçekleştirmeyi sağlar:

    
import { startTransition } from 'react';

function SearchComponent() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  function handleInput(e) {
    setQuery(e.target.value);
    startTransition(() => {
      const filtered = heavyFilterFunction(allData, e.target.value);
      setResults(filtered);
    });
  }

  return (
    <>
      <input onChange={handleInput} value={query} />
      <ResultsList results={results} />
    </>
  );
}       
    

Bu yapıda setQuery yüksek öncelikli olarak anında işlenir ve input alanı tepki verir. setResults ise startTransition içinde düşük öncelikli olarak işlenir ve ana thread'i bloke etmez.

Presentation Delay ve Layout Thrashing Sorunu

Presentation delay, event handler tamamlandıktan sonra tarayıcının değişiklikleri ekrana yansıtma süresidir. Bu süre, DOM değişikliklerinin tetiklediği layout hesaplamaları, style recalculation ve paint işlemlerinden oluşur. Layout thrashing, JavaScript'in DOM'dan okuma ve yazma işlemlerini sıralı olarak yapması sonucu tarayıcının layout'u defalarca yeniden hesaplamasıdır.

Layout thrashing'in klasik örneği şudur:

    
// YANLIŞ: Layout thrashing
elements.forEach(el => {
  const height = el.offsetHeight; // Layout okuma (zorla layout hesaplatır)
  el.style.height = height * 2 + 'px'; // Layout yazma
});

// DOĞRU: Batch okuma/yazma
const heights = elements.map(el => el.offsetHeight); // Tüm okumaları topla
elements.forEach((el, i) => {
  el.style.height = heights[i] * 2 + 'px'; // Tüm yazmaları topla
});     
    

İlk yaklaşımda her döngüde bir okuma ve bir yazma yapılır; tarayıcı her okumada layout'u yeniden hesaplar. İkinci yaklaşımda tüm okumalar önce yapılır, ardından tüm yazmalar yapılır; tarayıcı layout'u yalnızca bir kez hesaplar. Bu basit sıralama değişikliği, presentation delay'i 10 kata kadar azaltabilir.

requestAnimationFrame ile Görsel Güncellemelerin Zamanlanması

requestAnimationFrame (rAF), tarayıcının bir sonraki paint döngüsünde çalışacak kodu zamanlamak için kullanılır. DOM manipülasyonlarını rAF içinde yapmak, tarayıcının optimal zamanda layout ve paint hesaplamalarını yapmasını sağlar. Bu yaklaşım, presentation delay'i minimize eder.

Ancak rAF tek başına input delay sorununu çözmez. rAF callback'i, ana thread müsait olduğunda çalışır; long task devam ediyorsa rAF de bekler. Dolayısıyla rAF, presentation delay optimizasyonu için etkilidir; input delay için ise long task'ların parçalanması gerekir.

    
function updateUI(changes) {
  requestAnimationFrame(() => {
    changes.forEach(change => {
      change.element.style.transform = `translateY(${change.offset}px)`;
    });
  });
}    
    

transform ve opacity gibi compositor-only CSS özelliklerini kullanmak, layout ve paint aşamalarını atlayarak yalnızca composite aşamasında güncelleme yapar. Bu teknik, animasyonlarda ve geçişlerde presentation delay'i sıfıra yaklaştırır.

yield to Main Thread Tekniği ile Long Task Parçalama

Long task'ları parçalamanın en etkili yöntemi, görev içinde ana thread'e kontrol vermektir (yielding). Bu teknik, uzun süren bir JavaScript görevini küçük parçalara böler ve her parça arasında tarayıcıya kullanıcı girdilerini işleme fırsatı tanır. Böylece input delay düşer.

Modern yaklaşımda scheduler.yield() API'si (Chrome 115+) bu işlevi doğal olarak sağlar. Henüz tam tarayıcı desteği olmayan ortamlarda setTimeout(0) ile benzer etki elde edilir:

    
async function processLargeDataset(items) {
  const CHUNK_SIZE = 50;
  
  for (let i = 0; i < items.length; i += CHUNK_SIZE) {
    const chunk = items.slice(i, i + CHUNK_SIZE);
    processChunk(chunk);
    
    // Ana thread'e kontrol ver
    await new Promise(resolve => setTimeout(resolve, 0));
  }
} 
    

Bu yapıda 1.000 öğelik bir veri seti 50'şerli parçalara bölünür. Her 50 öğe işlendikten sonra setTimeout(0) ile ana thread'e kontrol verilir. Tarayıcı, bu arada bekleyen kullanıcı etkileşimlerini işler. Long task'ları 50 ms altında parçalara bölmek, INP'nin input delay fazını sıfıra yaklaştırır. Bu teknik, karmaşık filtreleme, sıralama ve veri dönüştürme işlemlerinde doğrudan uygulanmalıdır.

Web Worker ile Ağır Hesaplamaların Ana Thread'den İzolasyonu

Web Worker, JavaScript kodunu ana thread'den bağımsız bir arka plan thread'inde çalıştırır. Ana thread yalnızca UI güncellemeleri ve kullanıcı etkileşimleriyle ilgilenirken, ağır hesaplamalar Worker thread'inde paralel olarak gerçekleşir. Bu ayrım, input delay'i kökten ortadan kaldırır.

    
// worker.js
self.onmessage = function(e) {
  const result = heavyComputation(e.data);
  self.postMessage(result);
};

// main.js
const worker = new Worker('/worker.js');

function handleFilterClick(filterCriteria) {
  worker.postMessage(filterCriteria);
  worker.onmessage = function(e) {
    requestAnimationFrame(() => {
      renderResults(e.data);
    });
  };
}
    

Bu yapıda filtreleme butonu tıklandığında hesaplama Worker'a gönderilir. Ana thread serbest kalır ve kullanıcı sayfayla etkileşime devam edebilir. Sonuç geldiğinde rAF ile DOM güncellenir. E-ticaret sitelerinde ürün filtreleme, harita uygulamalarında rota hesaplama ve dashboard'larda veri agregasyonu, Web Worker kullanımının en yüksek getiri sağladığı senaryolardır.

React.memo, useMemo ve useCallback ile Gereksiz Re-render Önleme

React bileşen ağacında bir state güncellendiğinde, o bileşen ve tüm alt bileşenleri yeniden render edilir. Büyük bileşen ağaçlarında bu re-render zinciri, event handler'ın processing time'ını ciddi biçimde artırır. React.memo ile sarmalanan bileşenler, props'ları değişmediği sürece yeniden render edilmez.

    
const ProductCard = React.memo(function ProductCard({ product, onAddToCart }) {
  return (
    <div>
      <h3>{product.name}</h3>
      <button onClick={() => onAddToCart(product.id)}>Sepete Ekle</button>
    </div>
  );
});
    

Ancak React.memo tek başına yetmez. Parent bileşen her render'da yeni fonksiyon referansı oluşturuyorsa, onAddToCart prop'u her seferinde değişir ve memo etkisiz kalır. useCallback ile fonksiyon referansını stabilize etmek gerekir. useMemo ise pahalı hesaplama sonuçlarını cache'ler. Bu üç araç birlikte kullanıldığında, gereksiz re-render'lar minimize edilir ve processing time düşer.

Virtualization ile Büyük Liste Render Performansı

Binlerce öğelik listeler (ürün listesi, tablo satırları, yorum akışı) DOM'a eklendiğinde, her etkileşimde tüm öğelerin style recalculation ve layout hesaplamasına dahil olması INP'yi yükseltir. Virtualization (windowing), yalnızca viewport'ta görünen öğeleri DOM'a ekler; görünmeyen öğeler DOM'dan kaldırılır.

@tanstack/react-virtual kütüphanesi bu optimizasyonu sağlar:

    
import { useVirtualizer } from '@tanstack/react-virtual';

function ProductList({ products }) {
  const parentRef = useRef(null);
  const virtualizer = useVirtualizer({
    count: products.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 80,
  });

  return (
    <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
      <div style={{ height: virtualizer.getTotalSize() }}>
        {virtualizer.getVirtualItems().map(virtualRow => (
          <div key={virtualRow.key} style={{
            position: 'absolute',
            top: virtualRow.start,
            height: virtualRow.size,
          }}>
            <ProductCard product={products[virtualRow.index]} />
          </div>
        ))}
      </div>
    </div>
  );
}
    

10.000 öğelik bir liste, virtualization olmadan 10.000 DOM elementi oluşturur. Virtualization ile yalnızca ekranda görünen 10-15 element DOM'da bulunur. Bu fark, her etkileşimdeki DOM traversal ve layout hesaplama süresini 100 kat azaltabilir.

Debounce ve Throttle ile Etkileşim Frekansı Kontrolü

Kullanıcı bir arama kutusuna yazarken her tuş basımı bir etkileşim olarak kaydedilir. Her tuş basımında ağır bir filtreleme veya API çağrısı tetikleniyorsa, ardışık etkileşimlerin her biri yüksek INP üretir. Debounce, kullanıcı yazmayı durdurduktan belirli bir süre sonra işlemi tetikler. Throttle ise belirli aralıklarla işlemi çalıştırır.

    
function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

const debouncedSearch = debounce((query) => {
  startTransition(() => {
    const results = filterProducts(query);
    setResults(results);
  });
}, 300);
    

Bu yaklaşımda kullanıcı yazmayı bıraktıktan 300 ms sonra filtreleme başlar. Her tuş basımında değil, yalnızca yazma tamamlandığında ağır işlem çalışır. Bu kombinasyon (debounce + startTransition), arama kutusu etkileşimlerinde INP'yi dramatik biçimde düşürür.

CSS Containment ile Render Kapsamının Sınırlandırılması

CSS contain özelliği, tarayıcıya bir elemanın layout, style veya paint hesaplamalarının diğer elemanlardan bağımsız olduğunu bildirir. Bu bildirim, tarayıcının bir etkileşim sonrası yalnızca etkilenen alanın hesaplamalarını yapmasını sağlar; tüm sayfayı yeniden hesaplamaz.

    
.product-card {
  contain: layout style paint;
  content-visibility: auto;
  contain-intrinsic-size: 0 80px;
}
    

content-visibility: auto ise viewport dışındaki elemanların render'ını tamamen atlar. Bu özellik, uzun listelerde ve sayfa aşağısındaki içeriklerde render maliyetini sıfıra indirir. contain-intrinsic-size, elemanın render edilmeden önceki tahmini boyutunu belirleyerek scrollbar hesaplamalarının doğru yapılmasını sağlar. Bu iki CSS özelliğinin birlikte kullanımı, presentation delay'i özellikle uzun sayfalarda %40-60 oranında azaltır.

Üçüncü Parti Scriptlerin INP Etkisi ve İzolasyon Yöntemleri

Üçüncü parti scriptler, ana thread üzerinde kontrolsüz biçimde çalışarak input delay'in en büyük kaynağını oluşturur. Analytics, reklam, A/B test ve canlı sohbet scriptleri kendi zamanlayıcılarıyla periyodik olarak ana thread'i bloke eder. Bu blokaj, kullanıcı etkileşimiyle çakıştığında INP spike'ları üretir.

Partytown kütüphanesi, üçüncü parti scriptleri web worker'da çalıştırarak ana thread'den tamamen izole eder. Bu izolasyon, üçüncü parti kaynaklı input delay'i sıfıra indirir. LinkedIn üzerindeki web performans topluluklarında paylaşılan A/B test sonuçları gösteriyor ki, Partytown entegrasyonu sonrasında INP p75 değeri ortalama %35 iyileşiyor. Alternatif olarak, requestIdleCallback ile üçüncü parti scriptleri tarayıcının boş anlarında yüklemek de etkili bir yöntemdir; ancak Partytown kadar kapsamlı bir izolasyon sağlamaz.

Accordion, Dropdown ve Modal Bileşenlerinin INP Optimizasyonu

Etkileşimli UI bileşenleri (accordion, dropdown, modal, tab) kullanıcı tıklamasıyla tetiklenir ve görsel güncelleme üretir. Bu bileşenlerin INP performansı, açılma/kapanma animasyonlarının CSS mi yoksa JavaScript ile mi yönetildiğine bağlıdır.

CSS transition ve animation özellikleri compositor thread'inde çalışır ve ana thread'i bloke etmez. JavaScript ile yapılan animasyonlar ise requestAnimationFrame kullanılsa bile ana thread üzerinde çalışır. Dropdown menü açılırken transform: scaleY(1) ve opacity: 1 geçişi CSS ile yapıldığında, ana thread serbest kalır ve INP yalnızca event handler süresine bağlı olur. Aksine, element.style.height = calculatedHeight + 'px' ile JavaScript'te yapılan animasyonlar, her frame'de layout hesaplaması tetikler ve presentation delay'i artırır.

Form Etkileşimlerinde INP Optimizasyonu

Form alanları, INP açısından yoğun etkileşim üreten elemanlardır. Her tuş basımı, her checkbox tıklaması ve her dropdown seçimi ayrı bir etkileşim olarak ölçülür. Form state'inin yönetim biçimi, bu etkileşimlerin processing time'ını doğrudan belirler.

Kontrollü bileşen (controlled component) yaklaşımında her tuş basımı state güncellemesi tetikler ve bileşen ağacı yeniden render edilir. Büyük formlarda bu re-render zinciri INP'yi yükseltir. Çözüm, kontrollü olmayan bileşen (uncontrolled component) yaklaşımını veya form kütüphanelerini kullanmaktır. react-hook-form kütüphanesi, DOM referansları üzerinden çalışarak re-render'ları minimize eder ve form etkileşimlerinde INP'yi kontrollü bileşen yaklaşımına göre ortalama %60 düşürür.

Scroll ve Resize Event'lerinin Performans Etkisi

Scroll ve resize event'leri, saniyede 60-120 kez tetiklenir. Bu event'lere bağlı JavaScript fonksiyonları her tetiklemede çalışırsa, ana thread sürekli meşgul kalır ve kullanıcının diğer etkileşimleri için input delay oluşur. Bu durum, INP'nin en sinsi kaynaklarından biridir; çünkü sorun doğrudan kullanıcı tıklamasıyla değil, arka plandaki scroll dinleyicisiyle ilgilidir.

passive: true event listener seçeneği, tarayıcıya event handler'ın preventDefault() çağırmayacağını bildirir. Bu bildirim, tarayıcının scroll'u event handler'ı beklemeden başlatmasını sağlar:

    
window.addEventListener('scroll', handleScroll, { passive: true });
    

Scroll handler içindeki işlemleri requestAnimationFrame ile zamanlamak ve IntersectionObserver API'sini scroll event'i yerine kullanmak, ana thread üzerindeki yükü minimuma indirir. Sonsuz scroll, lazy loading ve yapışkan header gibi özelliklerde IntersectionObserver, scroll event'ine göre çok daha düşük INP etkisi üretir.

Search Console ve CrUX Verileriyle INP Takibi

Search Console'daki Core Web Vitals raporu, gerçek kullanıcı verilerine (field data) dayalı INP performansını gösterir. Bu rapor, sayfaları "İyi", "İyileştirme gerekiyor" ve "Kötü" kategorilerinde gruplar. Rapordaki "Mobil" ve "Masaüstü" sekmeleri, cihaz bazında INP durumunu ayrı ayrı gösterir.

Chrome User Experience Report (CrUX), 75. yüzdelik dilim (p75) INP değerini raporlar. Bu değer, kullanıcıların %75'inin yaşadığı INP'nin eşik altında olduğunu garanti eder. CrUX verileri, PageSpeed Insights üzerinden URL bazında sorgulanabilir. Sahadaki gerçek tecrübemiz gösteriyor ki, lab verisi (Lighthouse) ile field verisi (CrUX) arasında INP'de ortalama %30-50 fark oluyor. Çünkü lab ortamında üçüncü parti scriptler, uzantılar ve gerçek kullanıcı davranışları simüle edilemez. Optimizasyon kararlarını field verisine dayandırmak, gerçek dünya etkisini ölçmenin tek güvenilir yoludur.

INP Attribution API ile Darboğaz Kaynağının Tespiti

Web Vitals kütüphanesinin attribution build'i, INP'nin hangi etkileşimden, hangi elemandan ve hangi fazdan kaynaklandığını detaylı biçimde raporlar. Bu veri, optimizasyon önceliğini belirlemenin en doğrudan aracıdır:

    
import { onINP } from 'web-vitals/attribution';

onINP(metric => {
  console.log('INP:', metric.value);
  console.log('Element:', metric.attribution.interactionTarget);
  console.log('Type:', metric.attribution.interactionType);
  console.log('Input Delay:', metric.attribution.inputDelay);
  console.log('Processing:', metric.attribution.processingDuration);
  console.log('Presentation:', metric.attribution.presentationDelay);
});
    

Bu veriler analytics platformuna gönderildiğinde, hangi sayfa tipinde, hangi elemanda ve hangi fazda INP sorunu yoğunlaştığı istatistiksel olarak ortaya çıkar. Örneğin, ürün sayfalarındaki "Sepete Ekle" butonunun processing time'ı 250 ms ise, optimizasyon odağı doğrudan o butonun event handler'ına yönelir. Bu spesifiklik, genel performans iyileştirmelerine kıyasla çok daha hızlı ve ölçülebilir sonuç verir.

Mobil Cihazlarda INP Performansı ve İşlemci Farkı

Teoride doğru görünen ama pratikte patlayan nokta şudur: masaüstünde 50 ms süren bir JavaScript görevi, orta segment bir mobil cihazda 200-300 ms sürebilir. Mobil işlemciler masaüstü işlemcilerinden 3-6 kat yavaştır. Lighthouse'un CPU throttling'i (4x slowdown) bu farkı simüle etmeye çalışır, ancak gerçek cihaz çeşitliliğini tam yansıtamaz.

Bu nedenle INP optimizasyonu, düşük performanslı cihazları hedef almalıdır. Chrome DevTools Performance sekmesinde CPU throttling'i 6x'e ayarlayarak profil almak, orta segment Android cihazlardaki deneyimi daha gerçekçi biçimde simüle eder. Gerçek cihaz testi için BrowserStack veya kendi test cihazınızla Remote Debugging yaparak INP değerlerini ölçün. INP optimizasyonu, en yavaş cihazın deneyimini iyileştirmeyi hedeflemelidir; hızlı cihazlar zaten yeterli performans sağlar.

INP Performans Bütçesi ve CI/CD Entegrasyonu

İşin mutfağında durum farklıdır: INP optimizasyonu tek seferlik bir müdahale değil, her sprint'te korunması gereken bir standarttır. Yeni eklenen her bileşen, her event handler ve her üçüncü parti script entegrasyonu, INP'yi bozma potansiyeli taşır. Bu riski yönetmenin yolu, CI/CD pipeline'ında INP bütçesi tanımlamak ve her deployment öncesinde otomatik kontrol uygulamaktır.

Lighthouse CI ile INP eşiğini tanımlayarak build kalite kapısı oluşturun. Gerçek kullanıcı verilerini izleyen bir RUM (Real User Monitoring) dashboard'u kurup, INP p75 değerinin 200 ms altında kalıp kalmadığını günlük takip edin. INP spike'ları tespit edildiğinde, attribution verisiyle kaynağı hızla izole edip düzeltin. Bu üç katmanlı izleme mekanizması (CI kalite kapısı, RUM dashboard, attribution analizi), INP performansının uzun vadede kontrol altında kalmasını sağlayan tek sürdürülebilir yaklaşımdır.

🚀 Şimdi Harekete Geçin

Bu rehberi teori olmaktan çıkar — 5 farklı AI ile test et veya ekibinle paylaş.

WhatsApp