INP nasıl düzeltilir? Etkileşim gecikmesinin sebepleri ve çözümleri
Kullanıcı bir butona tıklıyor, sayfa bir süre donuk kalıyor, sonra tepki veriyor. Lighthouse puanı yüksek görünse bile Search Console'da INP uyarısı geliyorsa sorun tam olarak budur: ana iş parçacığı (main thread) o anda başka işle meşgul.
INP, Mart 2024'te FID'in yerini aldı ve FID'den çok daha zor bir metrik. Sadece ilk etkileşimi değil, sayfa ömrü boyunca yapılan etkileşimleri izliyor. Bu yüzden "ilk yüklemede JavaScript'i ertele" gibi eski taktikler tek başına yetmiyor.
INP tam olarak neyi ölçüyor?
INP (Interaction to Next Paint), bir tıklama, dokunma veya klavye etkileşimi ile tarayıcının bir sonraki kareyi ekrana çizmesi arasındaki süreyi ölçer. Kaydırma ve üzerine gelme (hover) sayılmaz. Sayfa kapanırken en yavaş etkileşimlerden biri raporlanır; çok sayıda etkileşim olan sayfalarda tek tük aykırı değerler hesaptan düşülür. Kısacası INP, "en kötüye yakın" etkileşimi temsil eder.
Her etkileşim üç parçadan oluşur:
- Giriş gecikmesi (input delay): Kullanıcı tıkladı ama ana iş parçacığı başka bir görevi bitirmeden olay işleyicisi çalışamıyor.
- İşleme süresi (processing duration): Olay işleyicilerinizin (click, keydown vb.) çalıştığı süre.
- Sunum gecikmesi (presentation delay): İşleyiciler bittikten sonra stil hesaplama, layout ve paint ile yeni karenin ekrana gelmesi.
Hangi parçanın büyük olduğunu bilmeden düzeltme yapmak, karanlıkta ok atmaktır. Giriş gecikmesi büyükse sorun başka bir script'tir; işleme süresi büyükse sizin kodunuzdur; sunum gecikmesi büyükse DOM ve render maliyetidir.
Eşikler ve saha verisi
| INP değeri | Değerlendirme |
|---|---|
| 200 ms ve altı | İyi |
| 200-500 ms | İyileştirme gerekli |
| 500 ms üstü | Kötü |
Değerlendirme gerçek kullanıcıların 75. yüzdeliğine göre yapılır (CrUX verisi). Yani ziyaretçilerin dörtte üçünün deneyimi 200 ms'nin altında olmalı.
Burada önemli bir ayrım var: INP bir saha (field) metriğidir. Laboratuvar testinde kimse tıklamadığı için Lighthouse INP ölçemez. Laboratuvarda en yakın vekil TBT'dir (Total Blocking Time). TBT yüksekse INP'nin de kötü olma ihtimali yüksektir, ama TBT'nin iyi olması INP'nin iyi olduğunu garanti etmez; çünkü INP, yükleme bittikten çok sonra yapılan etkileşimlerde de bozulabilir.
Yavaş etkileşimleri bulmak
Ben şu sırayla ilerliyorum:
- Search Console > Önemli Web Verileri (Core Web Vitals) raporu: Hangi URL gruplarında INP sorunu olduğunu gösterir. Mobil ve masaüstü ayrı raporlanır.
- PageSpeed Insights: Tek bir URL veya tüm origin için CrUX saha verisini gösterir. Yeterli trafik yoksa veri çıkmaz.
- web-vitals kütüphanesi (attribution sürümü): Gerçek kullanıcılardan hangi elemanın, hangi etkileşim türünün ve hangi fazın yavaş olduğunu toplar. Asıl teşhis burada yapılır.
- Chrome DevTools > Performance paneli: Şüpheli etkileşimi kendi makinenizde CPU yavaşlatma (throttling) açıkken kaydedip hangi fonksiyonun ana iş parçacığını tuttuğunu görürsünüz. Güncel sürümlerde panel, siz sayfayla etkileşirken yerel INP değerini canlı olarak da gösteriyor.
web-vitals kütüphanesinin attribution sürümüyle en basit kurulum şöyle:
Konsola yazmak geliştirme için yeterli. Canlıda bu veriyi navigator.sendBeacon() ile kendi uç noktanıza gönderip interactionTarget değerine göre gruplamak, hangi butonun veya menünün sorunlu olduğunu birkaç gün içinde netleştirir. Ücretli bir RUM aracına gerek yok; küçük bir PHP betiği ve bir tablo yeterli.
En sık görülen sebepler
- Uzun görevler (long tasks): 50 ms'den uzun süren her JavaScript görevi ana iş parçacığını kilitler. Tıklama o sırada gelirse beklemek zorunda kalır.
- Ağır üçüncü parti script'ler: Etiket yöneticileri, sohbet widget'ları, reklam ve A/B test script'leri kendi zamanlamalarıyla çalışır ve giriş gecikmesini şişirir.
- Büyük DOM: Binlerce düğümlü bir sayfada küçük bir sınıf değişikliği bile pahalı stil ve layout hesaplamasına yol açar. Bu, sunum gecikmesinde görünür.
- Hydration: React, Vue gibi framework'lerde sayfa sunucudan gelir ama etkileşimli hale gelmesi için tüm bileşenlerin istemcide yeniden bağlanması gerekir. Bu sırada yapılan tıklamalar bekler.
- Zorunlu senkron layout: Bir döngüde önce stil yazıp hemen ardından
offsetHeightgibi bir ölçüm okumak, tarayıcıyı her adımda layout hesaplamaya zorlar (layout thrashing).
Çözümler
Uzun görevleri bölmek ve ana iş parçacığına yol vermek
En etkili teknik, işi parçalara ayırıp aralarda tarayıcıya nefes aldırmaktır. scheduler.yield() bunun için tasarlandı; desteklemeyen tarayıcılarda setTimeout ile geri düşüyoruz:
Son örnekteki desen önemli: kullanıcıya hemen bir tepki gösterip (buton durumu, spinner) ağır işi bir sonraki göreve bırakırsanız, bir sonraki kare hemen çizilir ve INP düşer. İş yine yapılır, ama kullanıcı bekletilmez.
Debounce ve gereksiz işi azaltmak
Arama kutusunda her tuş vuruşunda filtreleme veya istek yapmak klasik bir INP katilidir. Tuş vuruşunu hemen ekrana yansıtın, pahalı işi 200-300 ms'lik bir debounce ile geciktirin. Aynı mantık resize ve input olayları için de geçerli.
İşi ana iş parçacığından çıkarmak
Veri işleme, sıralama, büyük JSON ayrıştırma gibi DOM'a dokunmayan işler Web Worker'a taşınabilir. Worker ayrı bir iş parçacığında çalışır; ana iş parçacığı etkileşimlere açık kalır.
DOM'u küçültmek
Görünmeyen menü ağaçlarını, sekmelerin içindeki devasa listeleri ilk yüklemede DOM'a koymamak veya sayfalamak sunum gecikmesini doğrudan azaltır. Ekran dışı büyük bölümler için CSS content-visibility: auto da işe yarar. Layout thrashing için kural basit: önce tüm ölçümleri okuyun, sonra tüm yazma işlemlerini yapın.
Üçüncü parti script'leri ertelemek
Her script'i tek tek sorgulayın: gerçekten her sayfada mı gerekli? Sohbet widget'ını kullanıcı ilk etkileşimde veya birkaç saniye sonra yüklemek, etiket yöneticisindeki ölü etiketleri temizlemek, A/B test script'ini sadece test yapılan sayfalara koymak çoğu zaman kod yazmaktan daha fazla kazandırır.
Hydration maliyetini düşürmek
Framework kullanıyorsanız, etkileşim gerektirmeyen bölümleri statik bırakmak (kısmi veya ada tipi hydration), büyük bileşenleri tembel yüklemek ve istemciye giden JavaScript miktarını azaltmak gerekir. SSR ve SSG seçenekleri için React/Vue sitelerinde SEO: SSR, SSG, prerender yazısına bakabilirsiniz.
INP ve SEO ilişkisi hakkında dürüst bir not
Core Web Vitals, Google'ın sayfa deneyimi sinyallerinin bir parçası; ama alakalı ve iyi içeriğin yerini tutmaz. INP'yi 350 ms'den 180 ms'ye indirmek tek başına sıralamayı uçurmaz. Buna karşın takılan bir sayfa kullanıcıyı gerçekten kaçırır; özellikle filtreli kategori sayfaları ve formlar dönüşümü doğrudan etkiler. Ben INP'yi önce kullanıcı sorunu, sonra SEO sinyali olarak görüyorum.
Diğer iki metrik için LCP'yi 2,5 saniyenin altına indirmek ve CLS: sayfa kaymasını sıfırlamak yazılarına da göz atın. Google'ın metrik tanımı için web.dev INP sayfası güvenilir kaynak.
Kontrol listesi
- Search Console Önemli Web Verileri raporunda INP sorunlu URL gruplarını belirledim.
- web-vitals attribution ile gerçek kullanıcılardan hedef eleman ve faz verisini topluyorum.
- Hangi fazın (giriş, işleme, sunum) baskın olduğunu biliyorum.
- 50 ms'den uzun görevleri
scheduler.yield()veyasetTimeoutile böldüm. - Tıklamada önce görsel geri bildirim, sonra ağır iş prensibini uyguladım.
- Arama ve filtre girişlerine debounce ekledim.
- Üçüncü parti script'lerin listesini çıkarıp gereksizleri kaldırdım veya erteledim.
- DOM boyutunu ve layout thrashing yapan kodları gözden geçirdim.
- Değişikliklerden sonra saha verisinin güncellenmesi için 28 günlük CrUX penceresini beklemem gerektiğini biliyorum.
Comments / questions
If you have a question about any topic or wish to contact me: Telegram or send an email to [email protected] Thanks!