2024 yılının Mart ayında Google, Core Web Vitals ailesinde sessiz ama son derece önemli bir değişiklik yaptı: FID (First Input Delay) metriği emekliye ayrıldı ve yerini INP (Interaction to Next Paint) aldı. Bu değişiklik yalnızca bir metriğin yerini başka bir metriğin almasından ibaret değil. INP, kullanıcı etkileşim kalitesini ölçmenin çok daha kapsamlı ve gerçekçi bir yolu olarak tasarlandı.
Peki INP tam olarak ne ölçüyor? FID’den neden daha iyi? Sitenizin INP puanı neden yüksek olabilir ve bunu düzeltmek için ne yapabilirsiniz?
Bu rehberde INP’yi temelden ele alacak, teknik mekanizmasını açıklayacak, performansı etkileyen nedenleri inceleyecek ve JavaScript optimizasyon tekniklerinden araç seçimine kadar geniş bir yelpazede pratik çözümler sunacağız. Core Web Vitals hakkında genel bir bakış için bu rehbere göz atabilirsiniz.
INP Nedir?
INP (Interaction to Next Paint), bir kullanıcı web sayfasıyla etkileşime girdiğinde — tıklama, dokunma veya klavye tuşuna basma — tarayıcının bu etkileşime yanıt olarak ekranı ne kadar sürede güncellediğini ölçen bir performans metriğidir.
Daha açık bir ifadeyle: Kullanıcı bir butona tıkladığında, tarayıcının o tıklamayı işlemesi ve görsel bir geri bildirim üretmesi arasında geçen süre INP’yi belirler. Bu süre ne kadar kısaysa, site o kadar “duyarlı” hissettiriri.
INP, bir sayfayı ziyaret süresince gerçekleşen tüm etkileşimlerin gecikmelerini toplar ve genel olarak en yüksek gecikmeyi (bazı aykırı değerler hariç) temsil eden bir puan üretir. Yani tek bir kötü etkileşim bile genel puanı olumsuz etkileyebilir.
INP’nin Temel Özellikleri
- Yalnızca tıklama, dokunma ve klavye girdilerini ölçer (kaydırma ve yakınlaştırma dahil değildir)
- Sayfa ömrü boyunca tüm etkileşimleri izler
- Tek bir gecikme değeri değil, ziyaret süresindeki en yüksek gecikmeyi temsil eden bir skor üretir
- Gerçek kullanıcı verileri (RUM — Real User Monitoring) üzerinden değerlendirilir
- Chrome Kullanıcı Deneyimi Raporu (CrUX) aracılığıyla sahadan elde edilir
FID ile INP Arasındaki Temel Fark
FID (First Input Delay) yıllarca kullanıcı etkileşim duyarlılığını temsil eden metrik olarak kullanıldı. Ancak ciddi bir kısıtı vardı: yalnızca sayfadaki ilk etkileşimi ölçüyordu ve yalnızca input delay (giriş gecikmesi) kısmını kapsıyordu.
Bu yaklaşım, gerçek dünya kullanıcı deneyimini yeterince yansıtmıyordu. Bir kullanıcı sayfaya girip ilk tıklamasını yaptığında site hızlı görünebilir; ama sayfa boyunca onlarca etkileşim gerçekleştirdiğinde birkaç kötü an tüm deneyimi mahvedebilir. FID bu durumu hiç yakalamıyordu.
Karşılaştırma Tablosu
| Özellik | FID | INP |
|---|---|---|
| Ölçülen etkileşim | Yalnızca ilk | Tüm etkileşimler |
| Ölçülen bileşen | Yalnızca input delay | Input delay + processing + presentation |
| Temsil edilen değer | İlk gecikme | En yüksek gecikme (p98) |
| Durum | Emekli (Mart 2024) | Aktif Core Web Vitals metriği |
| İyi eşiği | <100ms | <200ms |
| Kötü eşiği | >300ms | >500ms |
FID’in yalnızca ilk etkileşimi ölçmesi, bazı sitelerin gerçekte yavaş bir etkileşim deneyimi sunmalarına karşın iyi FID puanları almasına yol açıyordu. INP bu açığı kapatarak kullanıcı deneyiminin çok daha doğru bir temsilini sunuyor.
INP Nasıl Hesaplanır?
INP’nin hesaplanması üç ayrı bileşenden oluşur. Bu üç bileşenin toplamı, tek bir etkileşim için INP değerini verir.
1. Input Delay (Giriş Gecikmesi)
Kullanıcı bir etkileşim başlattığında, tarayıcı bu girdiyi hemen işleyemeyebilir. Ana iş parçacığı (main thread) başka bir görevle meşgulse, giriş olayı kuyruğa girer ve bekler. Bu bekleme süresi input delay’dir.
Örneğin bir analytics scripti tam o an 300 ms’lik ağır bir hesaplama yapıyorsa ve siz bu süre içinde bir butona tıklarsanız, tarayıcı tıklamayı ancak bu görev bitince algılayabilir. Bu 300 ms doğrudan input delay olarak INP puanınıza yansır.
2. Processing Time (İşleme Süresi)
Tarayıcı girişi algıladıktan sonra, bu girişe bağlı olay dinleyicilerini (event listeners) çalıştırır. onclick, onkeydown, onpointerdown gibi handler’ların tamamı bu aşamada yürütülür. Handler’lar ne kadar yavaşsa, processing time o kadar artar.
Ağır DOM manipülasyonları, senkron AJAX çağrıları veya karmaşık hesaplamalar içeren event handler’lar bu aşamada gecikmelere yol açar.
3. Presentation Delay (Sunum Gecikmesi)
Olay handler’ları tamamlandıktan sonra tarayıcı, değişen CSS stillerini hesaplar (style recalculation), düzeni yeniden oluşturur (layout), boyama yapar (paint) ve bu pikselleri ekrana kompozitleler. Tüm bu aşamalar presentation delay’i oluşturur.
Çok sayıda DOM düğümünü etkileyen değişiklikler, karmaşık CSS kuralları veya CSS animasyonları bu aşamanın uzamasına neden olabilir.
Formül
INP = max(input delay + processing time + presentation delay)
Daha teknik bir ifadeyle: Sayfa boyunca gerçekleşen tüm etkileşimler için bu üç değerin toplamı hesaplanır. Kullanıcı çok sayıda etkileşim gerçekleştirmişse, 98. yüzdelik dilim (p98) değeri rapor edilir; yani neredeyse en kötü etkileşim puanı INP’yi belirler.
INP Eşik Değerleri
Google, INP için üç kategori belirlemiştir:
| Kategori | Değer |
|---|---|
| İyi | <200ms |
| Geliştir | 200ms – 500ms |
| Kötü | >500ms |
200 ms neden sınır? İnsan algısı açısından 100–200 ms aralığındaki gecikmeler “anlık” hissettirirken, 200 ms üzeri gecikmeler kullanıcı tarafından fark edilmeye başlar. 500 ms geçildiğinde çoğu kullanıcı “sayfa yavaş” ya da “dondu” izlenimi edinir.
Hedef, sayfanızdaki tüm etkileşimlerin — özellikle 75. yüzdelik dilim (p75) kullanıcı verisi baz alındığında — 200 ms altında kalmasını sağlamaktır.
INP’yi Kötüleştiren Nedenler
INP puanınız yüksekse, bunun birkaç temel nedeni olabilir. Her biri main thread (ana iş parçacığı) üzerinde baskı oluşturarak etkileşim gecikmelerini artırır.
Uzun Görevler (Long Tasks)
Tarayıcı, JavaScript’i tek bir iş parçacığında çalıştırır. Bu iş parçacığında 50 ms veya daha uzun süren herhangi bir görev “uzun görev” (long task) olarak sınıflandırılır ve kullanıcı etkileşimlerini bloke edebilir.
Uzun görevler nerede ortaya çıkar?
- Büyük JavaScript paketlerinin ayrıştırılması ve derlenmesi
- Karmaşık hesaplamalar yapan fonksiyonlar
- Sayfalara yüklenen üçüncü taraf scriptlerin başlatılması
- Büyük veri listelerinin senkron olarak işlenmesi
- React, Angular veya Vue gibi framework’lerin ilk render aşamaları
Chrome DevTools Performance panelinde uzun görevler kırmızıyla işaretlenir ve kolayca tespit edilebilir.
Main Thread Engelleme
Ana iş parçacığı hem JavaScript çalıştırmaktan hem de render işlemlerinden sorumludur. Bir JavaScript görevi çalışırken kullanıcı etkileşimleri sıraya alınır; yani kullanıcı ne kadar tıklarsa tıklasın, görev bitene kadar yanıt alınamaz.
Sık karşılaşılan engelleme senaryoları:
- Senkron XHR çağrıları: Artık nadiren kullanılsa da bazı eski kodlarda main thread’i tamamen dondurur
- Masif JavaScript dosyaları: Tek bir büyük bundle’ın ayrıştırılması yüzlerce ms sürebilir
- İç içe döngüler: Büyük veri kümelerinde O(n²) karmaşıklığındaki algoritmalar
- Zorla senkronize layout işlemleri:
offsetWidthgibi değerlerin okunup hemen ardından stil değişikliklerinin uygulanması (layout thrashing)
Ağır Event Handler’lar
Bir butona tıklandığında tetiklenen olay dinleyicisi içinde çok fazla iş yapılması, processing time bileşenini şişirir. Yaygın örnekler:
- Tıklama sonrası büyük bir API yanıtını senkron olarak DOM’a yazma
- Filtreleme veya arama işlemleri için tüm listeyi senkron döngüyle tarama
- Modal açılışında karmaşık animasyon hesaplamaları yapma
- Her tuş basımında tam metin araması tetikleme
Üçüncü Taraf Scriptler
Reklam scriptleri, canlı destek widget’ları, sosyal medya eklentileri ve analytics araçları main thread üzerinde ciddi yük oluşturabilir. Bu scriptler üzerinde kontrol sahibi olmak zordur ama etkilerini azaltmak mümkündür.
Aşırı DOM Boyutu
DOM’da çok sayıda düğüm bulunması hem style recalculation hem de layout süresini uzatır. Özellikle küçük bir değişikliğin bile binlerce düğümü etkilediği durumlarda presentation delay önemli ölçüde artar.
INP Optimizasyon Teknikleri
INP’yi iyileştirmenin özü, main thread üzerindeki yükü azaltmak ve uzun görevleri kısa, kesintiye izin veren parçalara bölmektir.
1. Uzun Görevleri Parçalama: yield ve scheduler.yield
JavaScript’te bir görev başladığında, tarayıcı o görevi tamamlamadan başka bir şey yapamaz. Uzun bir görevi parçalara bölerek arasına “nefes alma noktaları” eklemek, tarayıcıya bekleyen etkileşimleri işleme fırsatı tanır.
setTimeout ile klasik yield:
function yieldToMain() {
return new Promise(resolve => setTimeout(resolve, 0));
}
async function processLargeList(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// Her 50 öğede bir main thread'e nefes ver
if (i % 50 === 0) {
await yieldToMain();
}
}
}
scheduler.yield() ile modern yaklaşım:
scheduler.yield() API’si, setTimeout(0) yerine daha akıllı bir yield mekanizması sunar. Görevleri öncelik sırasına göre zamanlayabilirsiniz:
async function processWithScheduler(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// scheduler.yield destekleniyorsa kullan
if ('scheduler' in window && 'yield' in scheduler) {
await scheduler.yield();
} else {
// Fallback: setTimeout
await new Promise(resolve => setTimeout(resolve, 0));
}
}
}
scheduler.yield() özellikle Chrome 129+ sürümlerinde mevcut olup, görevin önceliğini koruyarak daha iyi bir zamanlama kalitesi sağlar.
isInputPending ile akıllı yield:
async function smartProcess(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// Yalnızca bekleyen giriş varsa ger
if (navigator.scheduling?.isInputPending()) {
await yieldToMain();
}
}
}
Bu yaklaşım, bekleyen bir kullanıcı etkileşimi yokken sürekli yield yapmaktan kaçınır; böylece görev hem hızlı tamamlanır hem de gerçekten gerekli olduğunda yol verir.
2. Web Workers ile Ağır Hesaplamaları Taşımak
Kullanıcı arayüzüyle doğrudan ilişkisi olmayan ağır hesaplamalar Web Worker’lara taşınabilir. Worker’lar ayrı bir iş parçacığında çalıştığından main thread’i hiç meşgul etmezler.
Ana thread:
// worker.js dosyasını başlat
const worker = new Worker('/js/heavy-worker.js');
// Veriyi gönder
worker.postMessage({ items: largeDataArray });
// Sonucu bekle
worker.onmessage = function(event) {
const result = event.data;
updateUI(result);
};
worker.js:
self.onmessage = function(event) {
const { items } = event.data;
// Ağır hesaplama burada yapılır, main thread etkilenmez
const result = items.map(item => heavyTransform(item));
self.postMessage(result);
};
Web Worker’ların kısıtlarına dikkat edin: DOM’a erişemezler, window nesnesine sahip değillerdir ve ana thread ile yalnızca postMessage üzerinden iletişim kurabilirler. Bu nedenle yalnızca saf hesaplama görevleri için uygundurlar.
3. React 18 Concurrent Features
React 18 ile gelen Concurrent Mode, INP optimizasyonu için güçlü araçlar sunar. Concurrent Mode, React’in render işlemlerini kesintiye uğratılabilir parçalara bölmesini sağlar.
useTransition ile düşük öncelikli güncellemeler:
import { useState, useTransition } from 'react';
function SearchComponent() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
function handleChange(e) {
// Acil güncelleme: input değerini hemen güncelle
setQuery(e.target.value);
// Düşük öncelikli: arama sonuçları bekleyebilir
startTransition(() => {
const filtered = searchItems(e.target.value);
setResults(filtered);
});
}
return (
<div>
<input value={query} onChange={handleChange} />
{isPending ? <Spinner /> : <ResultList items={results} />}
</div>
);
}
startTransition içindeki güncellemeler “interruptible” (kesilebilir) olarak işaretlenir. Kullanıcı yeni bir tuşa basarsa React, devam eden render’ı bırakıp yeni girişi önce işler. Bu, her tuş basımında tüm listenin yeniden render edilmesinin getirdiği INP maliyetini dramatik biçimde azaltır.
useDeferredValue ile değer erteleme:
import { useState, useDeferredValue } from 'react';
function FilteredList({ items }) {
const [filter, setFilter] = useState('');
const deferredFilter = useDeferredValue(filter);
const filteredItems = items.filter(item =>
item.name.toLowerCase().includes(deferredFilter.toLowerCase())
);
return (
<>
<input
value={filter}
onChange={e => setFilter(e.target.value)}
placeholder="Ara..."
/>
<ul>
{filteredItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</>
);
}
useDeferredValue, input’un hemen güncellenip render pahalı bileşenin ertelenmesini sağlar. Kullanıcı hızlı yazarken liste bir adım geride kalır ama klavye hiçbir zaman kasılmaz.
4. Debounce ve Throttle ile Event Sıklığını Azaltma
Her tuş basımında veya her fare hareketinde ağır bir işlem tetiklemeniz gerekmiyorsa, bu olayları debounce veya throttle etmek önemli bir INP kazanımı sağlar.
Debounce: Kullanıcı durana kadar bekler, sonra işlemi yapar.
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
const handleSearch = debounce(function(value) {
// API çağrısı veya ağır filtreleme
fetchSearchResults(value);
}, 300);
document.getElementById('search').addEventListener('input', function(e) {
handleSearch(e.target.value);
});
Throttle: Belirli zaman aralıklarında en fazla bir kez çalışır.
function throttle(fn, limit) {
let lastRun = 0;
return function(...args) {
const now = Date.now();
if (now - lastRun >= limit) {
lastRun = now;
fn.apply(this, args);
}
};
}
const handleScroll = throttle(function() {
updateStickyHeader();
}, 100);
window.addEventListener('scroll', handleScroll);
Genel kural: Debounce için arama kutuları, form doğrulama; throttle için scroll olayları, resize olayları ve mousemove tercih edilir.
5. Code Splitting ile Gereksiz JavaScript’i Erteleme
Sayfa ilk yüklendiğinde kullanıcıya hemen gerekmeyen JavaScript kod bloklarını ayırmak hem ilk yükleme süresini hem de INP’yi iyileştirir. İlk yükte daha az kod = daha az ayrıştırma ve derleme = daha serbest main thread.
Dinamik import ile route-based code splitting:
// Modal bileşenini yalnızca gerektiğinde yükle
async function openModal() {
const { initModal } = await import('./modal.js');
initModal();
}
document.getElementById('open-btn').addEventListener('click', openModal);
Intersection Observer ile lazy loading:
const observer = new IntersectionObserver((entries) => {
entries.forEach(async entry => {
if (entry.isIntersecting) {
// Bileşen görünür alana girince yükle
const { initChart } = await import('./chart.js');
initChart(entry.target);
observer.unobserve(entry.target);
}
});
});
document.querySelectorAll('.chart-container').forEach(el => {
observer.observe(el);
});
React.lazy ile bileşen seviyesinde split:
import { lazy, Suspense } from 'react';
const HeavyDashboard = lazy(() => import('./HeavyDashboard'));
function App() {
return (
<Suspense fallback={<div>Yükleniyor...</div>}>
<HeavyDashboard />
</Suspense>
);
}
6. Event Handler’ları Optimize Etme
Olay dinleyicilerinin kendisini hafifletmek, processing time bileşenini doğrudan etkiler.
Gereksiz DOM okumalarından kaçının (layout thrashing):
// Kötü: Her iterasyonda layout tetikler
function badLoop(elements) {
elements.forEach(el => {
const height = el.offsetHeight; // DOM okuma
el.style.marginTop = height + 'px'; // DOM yazma — layout invalidate!
});
}
// İyi: Önce oku, sonra yaz
function goodLoop(elements) {
const heights = elements.map(el => el.offsetHeight); // Önce hepsini oku
elements.forEach((el, i) => {
el.style.marginTop = heights[i] + 'px'; // Sonra hepsini yaz
});
}
Event delegation ile handler sayısını azaltın:
// Kötü: Her öğeye ayrı listener
document.querySelectorAll('.list-item').forEach(item => {
item.addEventListener('click', handleItemClick);
});
// İyi: Tek bir parent listener
document.getElementById('item-list').addEventListener('click', function(e) {
const item = e.target.closest('.list-item');
if (item) handleItemClick(item);
});
7. Üçüncü Taraf Scriptleri Yönetme
Üçüncü taraf scriptler üzerinde tam kontrol sahibi olmasanız da etkilerini azaltabilirsiniz:
<!-- defer ile main thread'i bloke etmeden yükle -->
<script src="analytics.js" defer></script>
<!-- Kritik olmayan scriptler için async -->
<script src="chatbot.js" async></script>
<!-- Web Worker üzerinden çalıştırmak için Partytown gibi araçları değerlendirin -->
Scriptlerin hangi kaynaktan geldiğini ve ne kadar uzun görev ürettiğini Chrome DevTools’ta Third-party summary filtresiyle görebilirsiniz.
INP’yi Ölçme Araçları
Chrome DevTools Performance Paneli
DevTools’un Performance sekmesi, INP sorunlarını tespit etmek için birincil araçtır.
Nasıl kullanılır:
- Chrome DevTools’u açın (F12)
- Performance sekmesine geçin
- Kayıt düğmesine basın
- Yavaş hissettiren etkileşimleri gerçekleştirin
- Kaydı durdurun
Kayıt tamamlandığında:
- Long tasks kırmızı köşeli bloklar olarak görünür
- INP candidate interactions zaman çizelgesinde işaretlenir
- Her etkileşim için input delay, processing ve presentation bileşenleri ayrı ayrı görülebilir
INP bozulma noktasını bulmak için: Flame Chart görünümünde en uzun bölümleri inceleyin. Call stack’te hangi fonksiyonun ne kadar süre harcadığını görebilirsiniz. “Bottom-up” ve “Call Tree” sekmeleri darboğazı bulmayı kolaylaştırır.
PerformanceObserver API
Gerçek kullanıcıların etkileşim sürelerini kodunuz aracılığıyla takip etmek istiyorsanız PerformanceObserver kullanabilirsiniz.
Event Timing API ile etkileşim ölçümü:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Yalnızca pointer ve klavye olaylarını ölç
if (entry.interactionId) {
const inp = entry.processingEnd - entry.startTime;
console.log(`Etkileşim süresi: ${inp.toFixed(2)}ms`);
console.log(`Input delay: ${(entry.processingStart - entry.startTime).toFixed(2)}ms`);
console.log(`Processing: ${(entry.processingEnd - entry.processingStart).toFixed(2)}ms`);
// Analytics'e gönder
sendToAnalytics({
metric: 'INP',
value: inp,
element: entry.target?.tagName
});
}
}
});
observer.observe({ type: 'event', buffered: true, durationThreshold: 16 });
web-vitals kütüphanesi ile basit entegrasyon:
import { onINP } from 'web-vitals';
onINP(({ value, rating, entries }) => {
console.log(`INP: ${value}ms — ${rating}`);
// En kötü etkileşimi bul
const worstEntry = entries.reduce((worst, entry) =>
entry.duration > worst.duration ? entry : worst
, entries[0]);
console.log('En yavaş etkileşim:', worstEntry.name, worstEntry.target);
});
web-vitals kütüphanesi, Google’ın resmi olarak desteklediği ve CrUX ile tutarlı ölçüm yapan en güvenilir yöntemdir.
Chrome User Experience Report (CrUX)
CrUX, Chrome kullanıcılarının gerçek oturum verilerinden derlenen bir alan adı performans veri tabanıdır. Sitenizin sahadan gelen INP verilerini görmek için birkaç yol vardır:
PageSpeed Insights:
https://pagespeed.web.dev/ adresine sitenizin URL’sini girin. “Saha Verisi” bölümünde son 28 gün boyunca gerçek Chrome kullanıcılarından elde edilen INP değerini ve p75 dağılımını görebilirsiniz.
Google Search Console:
Search Console > Core Web Vitals raporu, sitenizin tüm URL’leri için toplu INP durumunu gösterir ve “zayıf” olarak işaretlenen sayfaları listeleri.
BigQuery üzerinden CrUX:
Daha derin analizler için CrUX verisi Google BigQuery’de herkese açık olarak sunulmaktadır. Ülke, cihaz türü ve URL bazında filtreleme yapabilirsiniz.
CrUX API:
const endpoint = 'https://chromeuxreport.googleapis.com/v1/records:queryRecord';
const apiKey = 'YOUR_API_KEY';
fetch(`${endpoint}?key=${apiKey}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
url: 'https://example.com/',
metrics: ['interaction_to_next_paint']
})
})
.then(res => res.json())
.then(data => {
const inp = data.record.metrics.interaction_to_next_paint;
console.log('P75 INP:', inp.percentiles.p75, 'ms');
console.log('Histogram:', inp.histogram);
});
Gerçek Dünya Senaryoları ve Çözümleri
Senaryo 1: E-ticaret Filtre Butonu Gecikmesi
Sorun: Kullanıcı ürün listesinde bir filtre butonuna tıkladığında 600 ms gecikme oluşuyor.
Teşhis: DevTools’ta kayıt alındığında, tıklama sonrasında 400 ms’lik bir uzun görev görünüyor. Bu görev, filtreleme işleminin tüm ürün listesini senkron olarak DOM’a yeniden yazmasından kaynaklanıyor.
Çözüm: Listenin yeniden oluşturulmasını startTransition ile erteleme ve sayfalama (pagination) veya sanal kaydırma (virtual scrolling) ekleme.
startTransition(() => {
setFilteredProducts(applyFilters(products, activeFilters));
});
Sonuç: INP 600 ms → 140 ms’e düşer.
Senaryo 2: Arama Kutusu Donması
Sorun: Her tuş basımında canlı arama yapılıyor; kullanıcı hızlı yazınca klavye girdileri gecikmeyle işleniyor.
Teşhis: Her input olayı, 1000 öğelik bir listeyi senkron filtreleyen bir fonksiyon tetikliyor.
Çözüm: 250 ms debounce + useDeferredValue kombinasyonu.
const deferredQuery = useDeferredValue(query);
const results = useMemo(
() => items.filter(item => item.name.includes(deferredQuery)),
[items, deferredQuery]
);
Sonuç: INP 480 ms → 90 ms’e düşer.
Senaryo 3: Üçüncü Taraf Chat Widget’ı
Sorun: Canlı destek widget’ı sayfa yüklenirken büyük bir JS dosyası çalıştırıyor ve bu, kullanıcının ilk etkileşim anında main thread’i bloke ediyor.
Çözüm: Widget’ı requestIdleCallback veya Intersection Observer ile yalnızca kullanıcı sayfada belirli bir süre kaldıktan sonra yükleyin.
// 5 saniye sonra veya kullanıcı belirli bir alana gelince yükle
setTimeout(() => {
const script = document.createElement('script');
script.src = 'https://chat-widget.com/widget.js';
document.body.appendChild(script);
}, 5000);
INP İyileştirmesinde Öncelik Sıralaması
Tüm bu teknikler arasında nereden başlayacağınızı belirlemek için aşağıdaki sırayı öneriyoruz:
- Ölçün: PageSpeed Insights ve Search Console’da gerçek INP değerinizi öğrenin
- Tespit edin: DevTools Performance panelinde en uzun görevleri bulun
- Event handler’ları hafifletin: Processing time’ı artıran ağır handler’ları optimize edin
- Görevleri parçalayın:
yieldveyascheduler.yieldile uzun görevleri böllün - Üçüncü tarafları erteleyin: Chat widget, reklam scriptleri gibi kaynakları ilk yükten çıkarın
- Framework özelliklerini kullanın: React 18 concurrent features veya benzeri araçları devreye alın
- Tekrar ölçün: Değişikliklerin etkisini gerçek kullanıcı verileriyle doğrulayın
INP ve SEO İlişkisi
INP, Core Web Vitals’in aktif bir bileşeni olarak Google’ın sıralama algoritmasına dahildir. Ancak INP’nin SEO etkisini doğru anlamak önemlidir:
- Core Web Vitals, “sayfa deneyimi” sinyalinin bir parçasıdır
- Kötü bir INP puanı, aynı anahtar kelimeyi hedefleyen kaliteli içeriklere sahip rakipler karşısında sizi dezavantajlı konuma düşürebilir
- INP’nin doğrudan sıralama etkisi nüanslıdır; ancak dolaylı etkileri (daha yüksek dönüşüm, düşük hemen çıkma oranı, daha uzun oturum süresi) SEO sinyallerini olumlu etkiler
INP’yi iyileştirmek, aynı zamanda kullanıcı deneyimini iyileştirir. Bu da organik trafiği artırmak için altyapıyı sağlamlaştırır. Teknik SEO hizmetlerimiz hakkında daha fazla bilgi almak için bu sayfayı inceleyebilirsiniz.
Sık Sorulan Sorular
INP ve TBT arasındaki fark nedir?
TBT (Total Blocking Time) ve INP ilişkili ama farklı metriklerdir. TBT, sayfa yükleme süresindeki uzun görevlerin toplamını ölçer ve Lighthouse gibi lab tabanlı araçlarda kullanılır. INP ise gerçek kullanıcı etkileşimlerini ölçer ve yalnızca alan verileriyle (CrUX) değerlendirilir. İkisi birbirini tamamlar: TBT iyi bir proxy metriktir ama INP gerçek kullanıcı deneyimini temsil eder.
INP değerim iyi ama kullanıcılar yavaş hissettiriyor; bu nasıl olabilir?
INP, tıklama ve klavye olaylarını ölçer; kaydırma veya animasyon akıcılığını kapsamaz. Kullanıcılarınız yavaş hissediyorsa CLS (layout shift), yavaş kaydırma (scroll jank) veya ağır animasyonlar sorun yaratıyor olabilir. Ayrıca INP p75 değeri iyi olsa bile p98 değeriniz yüksekse belirli etkileşimler ciddi gecikme yaşatıyor olabilir.
Mobil INP puanı neden masaüstünden çok daha kötü?
Mobil cihazların işlemcisi daha kısıtlıdır. Aynı JavaScript kodu, masaüstünde 100 ms’de tamamlanan bir görevi mobilde 400 ms’de tamamlayabilir. Bu nedenle mobil öncelikli optimizasyon hayati önemdedir. CrUX ve PageSpeed Insights, cihaz türüne göre ayrı ayrı raporlama sunar; her iki skorunuzu ayrı değerlendirin.
INP optimizasyonu React dışındaki framework’lerde nasıl yapılır?
Vue, Angular, Svelte gibi framework’lerin de kendi deferral ve chunking mekanizmaları bulunur. Vue’da nextTick ve async components, Angular’da NgZone.runOutsideAngular ve Signals, Svelte’de built-in reactivity benzer amaçlara hizmet eder. Ancak temel ilke sabittir: ağır işleri main thread’den çıkar veya parçalara böl.
Özet
INP, kullanıcıların bir web sitesiyle nasıl hissettiklerini ölçmenin bugüne kadar geliştirilen en kapsamlı ve gerçekçi yöntemidir. FID’den farklı olarak yalnızca ilk değil tüm etkileşimleri değerlendirir; yalnızca input delay değil, işleme ve sunum aşamalarını da kapsar.
200 ms altında tutulması gereken bu metrik, main thread üzerindeki yükün azaltılmasıyla iyileştirilebilir. Görevleri scheduler.yield ile parçalamak, ağır hesaplamaları Web Worker’lara taşımak, React 18 concurrent features’ı kullanmak, debounce/throttle uygulamak ve gereksiz kodu yalnızca gerektiğinde yüklemek en etkili teknikler arasındadır.
Optimizasyon sürecine PageSpeed Insights ve Chrome DevTools’la başlayın, gerçek kullanıcı verilerini web-vitals kütüphanesiyle ölçün ve değişikliklerinizin etkisini CrUX verileriyle doğrulayın. INP puanınızı iyileştirmek yalnızca sıralamayı değil, kullanıcılarınızın sitenizde geçirdiği her anı doğrudan etkiler.