Site Hızı & Performans

    INP (Interaction to Next Paint) Nedir, Nasıl İyileştirilir

    INP metriğinin bileşenleri, ölçüm yöntemleri ve ana iş parçacığını rahatlatma teknikleri.

    10 dk okuma Güncellendi: 25 Ağustos 2026

    Sitenizin açılışı iyi, LCP yeşil, hatta Lighthouse skoru 95 — ama Search Console'da INP kırmızı. Bu tablo düşündüğünüzden çok daha yaygın ve mantıklı bir açıklaması var: INP (Interaction to Next Paint) sayfanın açılışını değil, açıldıktan sonra kullanıcının yaptığı her tıklamaya ne kadar sürede cevap verdiğinizi ölçer. Yani menüyü açmak, filtre uygulamak, sepete eklemek gibi işler ağırsa açılış ne kadar hızlı olursa olsun INP kötü çıkar.

    Bu rehberde INP'nin üç bileşenini tek tek açacak, hangi tür JavaScript'in bu bileşenlerden hangisini şişirdiğini gösterecek ve sahada gerçekten işe yarayan düzeltmeleri kod örnekleriyle anlatacağım. Ayrıca kendi sitenizde hangi etkileşimin suçlu olduğunu bulmanın en hızlı yolunu, yani gerçek kullanıcı verisiyle etkileşim bazlı teşhis yapmayı da göstereceğim.

    INP Tam Olarak Neyi Ölçüyor#

    INP, sayfa ömrü boyunca yapılan tüm tıklama, dokunma ve klavye etkileşimlerinin gecikmesini gözlemler ve bunlardan en kötüye yakın olan bir tanesini raporlar. "En kötüye yakın" ifadesi kasıtlı: az sayıda etkileşim varsa en kötü değer alınır, etkileşim sayısı arttıkça bir miktar üst uç ayıklanır ki tek bir talihsiz donma tüm skoru mahvetmesin. Sonuç, kullanıcının gerçekten hissettiği yanıt verebilirliğe çok yakın bir sayıdır.

    Ölçülen süre üç parçadan oluşur ve iyileştirme stratejiniz hangi parçanın baskın olduğuna göre tamamen değişir:

    BileşenNe zaman başlar, ne zaman biterBaskınsa sorun nerede
    Input delayKullanıcı tıklar, olay dinleyicisi çalışmaya başlarAna iş parçacığı başka bir uzun görevle meşgul
    Processing timeDinleyici başlar, tüm dinleyiciler biterDinleyicinin kendi kodu ağır
    Presentation delayDinleyiciler biter, tarayıcı bir sonraki kareyi boyarAğır düzen/boyama, çok fazla DOM mutasyonu

    Bu ayrım pratikte şuna dönüşür: input delay yüksekse suçlu tıkladığınız butonun kodu değil, o sırada arka planda çalışan üçüncü taraf betiği veya hidrasyon işidir. Processing time yüksekse doğrudan kendi olay dinleyicinize bakmalısınız. Presentation delay yüksekse DOM'a tek seferde çok fazla dokunuyorsunuz ya da pahalı CSS kullanıyorsunuz demektir. Üç metriğin genel çerçevesi ve eşik değerleri için Core Web Vitals nedir yazısına bakabilirsiniz.

    Hangi Etkileşimin Suçlu Olduğunu Bulmak#

    INP'yi iyileştirmenin en büyük zaman kaybı, yanlış etkileşimi optimize etmektir. Lighthouse size INP vermez çünkü lab testinde kimse tıklamaz; bu yüzden teşhis mutlaka gerçek etkileşimler üzerinden yapılmalıdır. En hızlı yöntem, PerformanceObserver ile uzun etkileşimleri konsola dökmektir:

    // Konsola yapıştırın, sonra sayfayla normal şekilde etkileşime girin
    new PerformanceObserver((list) => {
      for (const e of list.getEntries()) {
        if (e.interactionId && e.duration > 100) {
          console.log(
            `${e.name} | süre: ${Math.round(e.duration)} ms`,
            `| gecikme: ${Math.round(e.processingStart - e.startTime)} ms`,
            e.target
          );
        }
      }
    }).observe({ type: "event", durationThreshold: 40, buffered: true });
    

    Bu betik hem etkileşimin toplam süresini hem de input delay kısmını ayrı ayrı verir; üçüncü sütunda ise hangi DOM öğesine tıklandığını görürsünüz. Birkaç dakika sayfayı gerçek bir kullanıcı gibi kullanın: menüyü açın, arama yapın, filtre uygulayın, sepete ekleyin. Konsolda 200 ms'yi aşan ne varsa listeniz odur.

    Ölçümü üretime taşımak isterseniz web-vitals kütüphanesinin onINP fonksiyonu size en kötü etkileşimin hedef öğesini de verir. Bu bilgiyi kendi uç noktanıza gönderirseniz, hangi bileşenin binlerce kullanıcıda takıldığını tahmin etmek yerine bilirsiniz:

    import { onINP } from "web-vitals";
    
    onINP((metric) => {
      const attr = metric.attribution || {};
      navigator.sendBeacon("/api/inp", JSON.stringify({
        deger: metric.value,
        hedef: attr.interactionTarget,   // ör: "button#sepete-ekle"
        tur: attr.interactionType,       // "pointer" veya "keyboard"
      }));
    }, { reportAllChanges: false });
    

    Tarayıcı üzerinde adım adım profil çıkarmak istediğinizde ise Performance paneli kaçınılmaz olur; panelin nasıl okunacağını Chrome DevTools performans paneli yazısında anlattım.

    Uzun Görevleri Bölmek: En Yüksek Getirili Müdahale#

    Ana iş parçacığı tek şeritli bir yoldur. 300 ms süren bir JavaScript görevi çalışırken kullanıcı tıklarsa, tarayıcı o tıklamayı işleyemez; görev bitene kadar bekler. İşte input delay tam olarak budur. Bu yüzden INP iyileştirmesinin bir numaralı kuralı şudur: 50 ms'den uzun süren hiçbir görev bırakmayın. Bunu yapmanın yolu işi bölmek ve aralarda tarayıcıya nefes aldırmaktır.

    Modern tarayıcılarda bunun standart yolu scheduler.yield()'dir; desteklenmediği yerde küçük bir yedek fonksiyon yazarsınız:

    // Tarayıcıya sıra vermek için taşınabilir yardımcı
    function nefesAl() {
      if (typeof scheduler !== "undefined" && scheduler.yield) {
        return scheduler.yield();
      }
      return new Promise((r) => setTimeout(r, 0));
    }
    
    async function buyukListeyiIsle(kayitlar) {
      for (let i = 0; i < kayitlar.length; i++) {
        satirIsle(kayitlar[i]);
        // Her 50 kayıtta bir tarayıcıya sıra ver
        if (i % 50 === 0) await nefesAl();
      }
    }
    

    İkinci teknik, olay dinleyicisi içindeki işi "kullanıcının hemen görmesi gereken" ve "sonra yapılabilecek" diye ikiye ayırmaktır. Kullanıcı butona bastığında butonun basılı görünmesi ve panelin açılması anında olmalı; analitik gönderimi, öneri hesaplaması, localStorage yazımı ise bir sonraki kareye ertelenmelidir:

    sepetButonu.addEventListener("click", async (e) => {
      // 1) Acil olan: kullanıcı geri bildirimi
      e.currentTarget.setAttribute("aria-busy", "true");
      rozetiArtir();
    
      // 2) Tarayıcı boyasın diye sırayı bırak
      await nefesAl();
    
      // 3) Acil olmayan: ağ, analitik, ağır hesap
      await sepeteEkle(urunId);
      olcumGonder("add_to_cart", { urunId });
    });
    

    Üçüncü teknik ise gerçekten ağır hesaplamaları (büyük JSON ayrıştırma, görüntü işleme, şifreleme, arama indeksi kurma) bir Web Worker'a taşımaktır. Worker ayrı bir iş parçacığında çalışır ve ana iş parçacığını hiç bloke etmez; kullanıcı arayüzü hesap devam ederken bile akıcı kalır. Bu üç tekniğin ölçülen etkisi, aynı sayfada tipik olarak şu şekilde dağılır:

    MüdahaleZorlukTipik INP kazancı
    Kullanılmayan üçüncü taraf betiğini kaldırmakDüşükÇok yüksek
    Uzun görevleri bölüp yield etmekOrtaYüksek
    Dinleyicide acil/acil olmayan ayrımıOrtaYüksek
    Ağır hesabı Web Worker'a taşımakYüksekOrta-yüksek
    Görsel/font optimizasyonuDüşükDüşük (INP'ye etkisi az)

    Son satır önemli: görsel sıkıştırmak LCP'yi düzeltir, INP'yi neredeyse hiç etkilemez. INP tamamen JavaScript ve düzen maliyeti meselesidir.

    Üçüncü Taraf Betikleri ve Çerçeve Yükü#

    Sahada gördüğüm INP problemlerinin çoğunda suçlu, sitenin kendi kodu değil; etiket yöneticileri, canlı destek widget'ları, ısı haritası araçları ve reklam kodlarıdır. Bunlar genelde sayfa yüklendikten sonra çalışmaya başlar ve tam da kullanıcının ilk etkileşimi yaptığı ana denk gelir. Yapılacak ilk iş, hangi betiğin ne kadar ana iş parçacığı süresi tükettiğini ölçmektir:

    // Uzun görevleri ve kaynaklarını listele
    new PerformanceObserver((list) => {
      for (const t of list.getEntries()) {
        console.log("Uzun görev:", Math.round(t.duration), "ms",
          t.attribution.map((a) => a.containerSrc || a.containerName).join(", "));
      }
    }).observe({ type: "longtask", buffered: true });
    

    Çıktıda tekrar tekrar aynı üçüncü taraf alan adını görüyorsanız kararınızı verin: gerçekten gerekli mi, gerekliyse geciktirilebilir mi, yoksa sunucu tarafında bir alternatifi var mı. Canlı destek widget'ını ilk kullanıcı etkileşiminde yüklemek, ısı haritasını yalnızca örneklem trafiğinde açmak ve analitik gönderimini sendBeacon ile yapmak çoğu sitede tek başına INP'yi iyi bölgeye taşır.

    React, Vue gibi çerçevelerle çalışıyorsanız iki ek başlığa bakın. Birincisi hidrasyon: sunucudan gelen HTML'e olay dinleyicilerinin bağlanması pahalı bir iştir ve tam da açılıştan sonraki ilk saniyelerde ana iş parçacığını doldurur. Bileşen bazlı (aşamalı) hidrasyon ya da adalar mimarisi bu maliyeti dağıtır. İkincisi gereksiz yeniden render: bir metin kutusuna yazarken tüm listeyi yeniden render eden bir yapı, her tuşta processing time'ı büyütür. Girdiyi yerel duruma bağlayıp arama işlemini geciktirmek (debounce) burada tek satırlık ama çok etkili bir düzeltmedir. JavaScript'in engelleme süresi ile INP arasındaki ilişkiyi daha derin görmek isterseniz TBT (Total Blocking Time) nedir yazısı iyi bir tamamlayıcıdır.

    Presentation Delay: DOM ve CSS Tarafı#

    Olay dinleyiciniz 5 ms sürüyor olabilir ama sonrasında tarayıcının ekranı güncellemesi 300 ms alıyorsa INP yine kötüdür. Bu üçüncü bileşen genelde göz ardı edilir. En yaygın sebebi, tek bir etkileşimde DOM'a yüzlerce kez dokunmaktır: bir listeye 500 satırı tek tek appendChild ile eklemek, her satırda tarayıcının düzeni yeniden hesaplamasına yol açar.

    Çözüm, DOM değişikliklerini toplu yapmak ve okuma-yazma sırasını karıştırmamaktır. Aşağıdaki iki desen sahada en çok işe yarayanlardır:

    // KÖTÜ: her satırda düzen yeniden hesaplanır
    satirlar.forEach((s) => liste.appendChild(satirOlustur(s)));
    
    // İYİ: tek seferde ekle
    const parca = document.createDocumentFragment();
    satirlar.forEach((s) => parca.appendChild(satirOlustur(s)));
    liste.appendChild(parca);
    

    CSS tarafında ise iki ayar büyük fark yaratır. content-visibility: auto, görünür alanın dışındaki bölümlerin düzen ve boyama maliyetini erteler; uzun sayfalarda etkileşim sonrası yeniden boyama süresini ciddi biçimde kısaltır. contain: layout paint ise bir bileşendeki değişikliğin tüm sayfayı yeniden hesaplatmasını engeller:

    /* Ekran dışı bölümlerin maliyetini ertele */
    .uzun-bolum {
      content-visibility: auto;
      contain-intrinsic-size: auto 800px; /* ölçülmüş gerçek yükseklik */
    }
    
    /* Bağımsız bir bileşeni izole et */
    .urun-karti {
      contain: layout paint;
    }
    

    contain-intrinsic-size değerini mutlaka ölçülmüş gerçek yükseklikle verin; boş bırakırsanız sayfa yüksekliği çöker, kaydırma çubuğu zıplar ve CLS'yi bozarsınız. Bu iki metrik birbirini kolayca sabote edebilir; CLS düzen kayması nasıl düzeltilir yazısındaki kurallarla birlikte uygulayın.

    Sık Yapılan Hatalar#

    Lighthouse skoruna bakıp INP'yi düzelttiğini sanmak. Lighthouse INP ölçmez; onun ölçtüğü TBT'dir ve ikisi ilişkili olsa da aynı şey değildir. Bir düzeltmenin işe yarayıp yaramadığını ancak gerçek etkileşim ölçümüyle anlarsınız.

    Her şeyi requestIdleCallback içine atmak. Boşta çalıştırma, sayfa sürekli meşgulse hiç çalışmayabilir ve mobilde davranışı çok değişkendir. Kullanıcının sonucunu beklediği işleri asla oraya koymayın; orası yalnızca gerçekten ertelenebilir işler içindir.

    Debounce'u yanlış yere koymak. Arama kutusunda debounce, ağ isteğinin önüne konur; girdinin ekrana yansımasının önüne değil. Kullanıcının yazdığı harfin görünmesi geciktirilirse INP düzelmez, kullanıcı deneyimi bozulur.

    Masaüstünde test edip mobili unutmak. Orta segment bir Android telefonun CPU'su masaüstünüzden 4-6 kat yavaştır. Aynı görev masaüstünde 40 ms sürerken mobilde 250 ms sürebilir. DevTools'ta CPU kısıtlamasını 4x veya 6x yapmadan alınan sonuç yanıltıcıdır.

    Sunucuyu suçlamak. INP tamamen tarayıcı tarafı bir metriktir; sunucunuzu iki kat hızlandırmak INP'yi neredeyse hiç değiştirmez. Sunucu iyileştirmesi TTFB ve LCP için doğrudur, INP için değil.

    Sıkça Sorulan Sorular#

    INP kaç milisaniye olmalı#

    İyi kabul edilen eşik 200 ms ve altıdır. 200-500 ms arası "iyileştirme gerekli", 500 ms üzeri "kötü" olarak sınıflandırılır. Google bu değeri gerçek kullanıcılarınızın 75. yüzdelik dilimi üzerinden hesaplar; yani ziyaretçilerinizin dörtte üçünün 200 ms'nin altında kalması gerekir. Kendi ölçümünüzde hedefi biraz aşağıda, örneğin 150 ms'de tutmak size güvenlik payı bırakır.

    INP'yi Lighthouse ile ölçebilir miyim#

    Hayır, doğrudan ölçemezsiniz. Lighthouse otomatik bir lab testidir ve sayfayla etkileşime girmez; etkileşim olmadığı için INP hesaplanamaz. Lighthouse size bunun yerine TBT (Total Blocking Time) verir; TBT yüksekse INP'nin de kötü olma ihtimali yüksektir ama bu bir tahmindir. INP için gerçek kullanıcı verisine, yani CrUX'e ya da kendi kurduğunuz web-vitals ölçümüne bakmalısınız.

    INP kötüyse hangi düzeltmeden başlamalıyım#

    Önce ölçün, sonra kesin. En kötü etkileşimin hangisi olduğunu PerformanceObserver ile bulun; ardından o etkileşimde input delay mi processing time mı baskın ona bakın. Input delay baskınsa muhtemel suçlu üçüncü taraf betikleridir ve en hızlı kazanç kullanılmayanları kaldırmaktır. Processing time baskınsa kendi olay dinleyicinizi bölün ve ağır işi erteleyin.

    Web Worker kullanmak zorunda mıyım#

    Hayır, çoğu site Worker'a hiç ihtiyaç duymadan hedefe ulaşır. Worker, gerçekten CPU yoğun ve bölünemeyen işler için doğru araçtır: büyük veri kümesi sıralama, görüntü işleme, istemci tarafı şifreleme gibi. Sıradan bir kurumsal site veya e-ticaret sayfasında INP problemi neredeyse her zaman gereksiz betik ve bölünmemiş uzun görevlerden kaynaklanır; bunları temizlemek yeterlidir.

    Önbellek eklentisi INP'yi düzeltir mi#

    Genellikle hayır. Önbellekleme, sunucunun HTML'i üretme süresini kısaltır; bu TTFB ve LCP için değerlidir ama tarayıcıdaki JavaScript yükünü azaltmaz. Bazı eklentilerin "JS erteleme" veya "kullanılmayan JS kaldırma" özellikleri INP'ye dolaylı fayda sağlayabilir, ancak bu özellikler yanlış yapılandırıldığında etkileşimleri tamamen bozabilir. Önbellek eklentisini LCP için, kod disiplinini INP için kullanın.

    INP mobilde neden her zaman daha kötü çıkıyor#

    Çünkü mobil cihazların işlemci gücü masaüstünün belirgin şekilde altındadır ve JavaScript ayrıştırma, derleme ve çalıştırma süreleri doğrudan CPU'ya bağlıdır. Aynı kod, orta segment bir telefonda masaüstünden birkaç kat uzun sürer. Ek olarak mobilde ağ gecikmesi daha yüksektir ve arka planda çalışan uygulamalar CPU'yu paylaşır. Bu yüzden testlerinizi mutlaka CPU kısıtlaması açıkken yapın ve kararlarınızı mobil verisine göre verin.

    Kapanış#

    INP'yi düzeltmenin sırrı, sihirli bir ayar değil disiplindir: uzun görev bırakmayın, olay dinleyicisinde yalnızca acil olanı yapın, gereksiz üçüncü taraf betiğini taşımayın ve DOM'a toplu dokunun. Aklınızda kalması gereken dört alışkanlık şunlar — önce ölçüp suçlu etkileşimi bulmak, 50 ms üstü her görevi bölmek, kullanıcı geri bildirimini asla ertelememek ve testleri CPU kısıtlaması açıkken mobil profilde yapmak.

    INP tamamen tarayıcı tarafı bir metrik olsa da, sağlam bir altyapı işin geri kalanını kolaylaştırır: hızlı bir sunucu sayfanın erken açılmasını sağlar, böylece hidrasyon ve üçüncü taraf yükü kullanıcının ilk tıklamasıyla çakışmaz. Kaynakların paylaşılmadığı bir ortam için VDS sunucu veya bulut sunucu paketlerimize, WordPress tarafında ölçülü bir eklenti seti ve sunucu düzeyinde önbellek için WordPress hosting çözümümüze bakabilirsiniz. Performans ayarlarını baştan sona bizim yapmamızı isterseniz sunucu yönetimi hizmetimiz bu işi de kapsıyor.

    INPCore Web VitalsJavaScript

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.