Düşük INP'nin nedenlerini belirleme

Etkileşimlere verilen yanıtların yavaş olması, sayfanın yavaş veya tamamen bozuk olduğu yönünde kötü bir izlenim bırakır. Interaction to Next Paint (INP), Event Timing API'yi temel alan bir metriktir. Sayfanın yanıt verme durumunu ölçmek için en kötü etkileşimi (bazı aykırı değerler hariç) ölçer.

Yanıt vermeyen bir web sayfasının temel nedenlerini belirlemek, özellikle kullanıcı etkileşimlerine ve cihaz özellikleri ile ağ koşulları gibi çevresel koşullara bağlı olduğu için zor olabilir. Bu durum, sayfa yükleme gibi daha tekrarlanabilir ve öngörülebilir bir senaryoya kıyasla teşhisi daha da zorlaştırır. Laboratuvar verileri, gerçek kullanıcı senaryolarının yalnızca küçük bir alt kümesini kopyalar. Bu nedenle, alandaki yavaş INP'nin nedenlerini ölçmek çok önemlidir.

Event Timing API, INP süresinin üç alt bölüme ayrılmasına olanak tanır: Giriş Gecikmesi (etkileşim gerçekleştiğinde zaten gerçekleşmekte olan işleme), İşleme Süresi (etkileşimin doğrudan sonucu olarak ortaya çıkan gecikmeler) ve Sunum Gecikmesi (etkileşimden sonra bir sonraki kareyi oluşturmaktan kaynaklanan gecikmeler). Bu, doğrudan etkileşim koduna atlamak yerine sorunun diğer kodda mı, etkileşim JavaScript kodunda mı yoksa tarayıcı işleme oluşturma güncellemelerinde mi olduğunu belirlemeye yardımcı olur.

JavaScript, stil yeniden hesaplama ve düzen çalışmasıyla ilgili daha fazla bilgi edinerek etkileşimi geciktirebilirsiniz. JS Self-Profiling API'yi kullanan tam bir performans izleme, performans sorunlarına neden olabilecek ağır bir çözümdür. Long Animation Frames API, yavaş çalışan JavaScript'i tanımlamak ve INP etkileşimleri sırasında stil yeniden hesaplama ile düzen maliyetleri arasında ayrım yapmak için sahada kullanılabilen hafif bir API'dir:

  • Komut dosyası düzeyinde zorunlu stil ve düzen (forcedStyleDuration ve forcedLayoutDuration): Giriş Gecikmesi veya İşleme Süresi sırasında çalışan bir komut dosyasında eşzamanlı stil yeniden hesaplamalarını (DOM mutasyonlarından sonra getComputedStyle() çağrılması gibi) ve zorunlu düzenleri/yeniden akışları (mutasyonlardan sonra getBoundingClientRect() veya offsetWidth okunması gibi) raporlar.
  • Kare düzeyinde oluşturma stili ve düzeni (styleDuration ve layoutDuration): Karenin oluşturma güncellemesi sırasında stilleri yeniden hesaplamak için harcanan süreyi ve düzeni güncellemek için harcanan süreyi raporlayarak yüksek sunum gecikmesini açıklamaya yardımcı olur.

Stil yeniden hesaplamasını düzenden ayırt etmek çok önemlidir çünkü bunların farklı temel nedenleri ve düzeltmeleri vardır: Yüksek stil süresi, pahalı CSS seçici eşleşmesine veya geniş stil geçersiz kılmaya işaret eder (seçicileri basitleştirerek veya kural kapsamını azaltarak düzeltilir). Yüksek düzen süresi ise pahalı geometri hesaplamalarına veya eşzamanlı düzen çakışmasına işaret eder (yazmadan önce DOM okumalarını toplu olarak işleyerek, DOM yapısını basitleştirerek veya CSS kapsayıcısını kullanarak düzeltilir).

Nasıl uygulanır?

INP'yi ham Event Timing API'den hesaplamak karmaşıktır ve çeşitli ayrıntılar içerir. Bu verileri toplamak için bir RUM aracı veya kitaplığı kullanmanız önerilir.

web-vitals, Google'ın açık kaynaklı bir kitaplığıdır. INP dahil olmak üzere Core Web Vitals'ı hesaplar ve INP etkileşimi için alt bölümler ile işlenmesi uzun süren animasyon çerçevesi verilerini de içerir.

web-vitals kitaplığını kullanarak INP etkileşimleri için ilişkilendirmeler alma

web-vitals kitaplığı, Core Web Vitals'ı ve diğer performans metriklerini ölçmek için kullanılan küçük bir kitaplıktır. onINP() işlevi, en yavaş etkileşimi belirlemek için kullanılabilir ve INP alt bölümleri, etkileşim sırasında yürütülen komut dosyaları ve İşlenmesi Uzun Süren Animasyon Çerçeveleri API'sini kullanan stil ve düzen süreleri hakkında bilgiler içerir.

// Use the attribution build to get Long Animation Frame data
// alongside the INP metric value.
import { onINP } from 'web-vitals/attribution';

onINP((metric) => {
  const { attribution } = metric;
  const longestScript = attribution.longestScript;

  // Sum rendering-phase style and layout durations across all LoAF entries
  // intersecting the INP interaction (primarily explains presentationDelay).
  let renderStyleDuration = 0;
  let renderLayoutDuration = 0;
  for (const entry of attribution.longAnimationFrameEntries) {
    renderStyleDuration += entry.styleDuration ?? 0;
    renderLayoutDuration += entry.layoutDuration ?? 0;
  }

  // Beacon script, style, and layout attribution for the INP interaction,
  // so you can identify the root cause in production.
  navigator.sendBeacon(
    '/analytics',
    JSON.stringify({
      name: 'INP',
      value: metric.value,
      // These fields give the INP subparts:
      inputDelay: attribution.inputDelay,
      presentationDelay: attribution.presentationDelay,
      processingDuration: attribution.processingDuration,
      interactionTarget: attribution.interactionTarget,
      // These fields identify which script function was responsible
      // for the longest processing during the INP interaction.
      invokerType: longestScript?.entry?.invokerType,
      sourceURL: longestScript?.entry?.sourceURL,
      sourceFunctionName: longestScript?.entry?.sourceFunctionName,
      sourceCharPosition: longestScript?.entry?.sourceCharPosition,
      // subpart indicates which phase (input delay, processing, or
      // presentation delay) the longest script overlapped with most.
      subpart: longestScript?.subpart,
      intersectingDuration: longestScript?.intersectingDuration,
      // Synchronous style and layout work forced inside the longest script
      // (with forcedStyleAndLayoutDuration as a combined fallback):
      forcedStyleDuration: longestScript?.entry?.forcedStyleDuration,
      forcedLayoutDuration: longestScript?.entry?.forcedLayoutDuration,
      forcedStyleAndLayoutDuration: longestScript?.entry?.forcedStyleAndLayoutDuration,
      // Rendering-phase style and layout work across the interaction's frames
      // (with totalStyleAndLayoutDuration as a combined fallback):
      renderStyleDuration,
      renderLayoutDuration,
      totalStyleAndLayoutDuration: attribution.totalStyleAndLayoutDuration
    })
  );
});

En İyi Uygulamalar

  • Gecikmenin hâlihazırda çalışan JavaScript (giriş gecikmesi), etkileşim için etkinlik işleyiciler JavaScript (işleme süresi) veya sonraki oluşturma (sunum gecikmesi) olup olmadığını belirlemek için başlangıçta INP alt bölümlerini KULLANIN.
  • Özellikle giriş gecikmesi ve işleme süresi için ek ayrıntı olarak en büyük engelleyici JavaScript'i tanımlamaya ÇALIŞIN.
  • Yüksek işleme süresi veya sunum gecikmesi teşhisi yaparken stil yeniden hesaplama (styleDuration, forcedStyleDuration) ile düzen (layoutDuration, forcedLayoutDuration) arasında ayrım YAPIN: Yüksek stil süreleri, pahalı CSS seçicileri veya geniş geçersiz kılmaları gösterirken yüksek düzen süreleri, DOM geometrisi darboğazlarını veya eşzamanlı düzen çakışmasını gösterir.
  • JS Self-Profiling API gibi daha yüksek çalışma zamanı ek yükü olan alternatifler yerine bu ek ayrıntıları sağlamak için Long Animation Frames API'yi tercih EDİN.
  • Başka bir RUM çözümü yoksa web-vitals kitaplığını KULLANIN. INP etkileşimini tanımlayabilir ve etkileşim sırasında yürütülen alt bölümler ve komut dosyaları hakkında bilgi içerir (İşlenmesi Uzun Süren Animasyon Çerçeveleri API'sini kullanarak).
  • Gerekli bilgileri yalnızca yerel olarak günlüğe kaydetmek yerine bir analiz hizmetine gönderin.

Tarayıcı desteği ve yedek stratejiler

Event Timing API, çoğu modern tarayıcıda kullanılabilir ve INP ile INP alt bölümlerini hesaplamak için gereklidir. Bu API'yi desteklemeyen tarayıcılar için INP ölçülemez.

Long Animation Frames API, isteğe bağlı ek ayrıntılar sağlar. Yedekler olmadan güvenle kullanılabilir. Çoğu durumda, belirlediği performans fırsatları diğer tarayıcılar için de geçerli olur.

Baseline hedefiniz, işlenmesi uzun süren animasyon çerçevesi API'sini (long-animation-frames) destekliyor ancak ayrı stil ve düzen süresi özelliklerini (PerformanceLongAnimationFrameTiming üzerinde styleDuration ve layoutDuration veya PerformanceScriptTiming üzerinde forcedStyleDuration ve forcedLayoutDuration) desteklemiyorsa birleştirilmiş stil ve düzen zamanlamalarına geri dönün:

  • Komut dosyalarında eşzamanlı zorunlu stil ve düzen çalışmaları için PerformanceScriptTiming üzerinde script.forcedStyleAndLayoutDuration kullanın.
  • Stil ve düzen çalışmalarını birleştirmek için web-vitals/attribution içinde metric.attribution.totalStyleAndLayoutDuration kullanın (veya her PerformanceLongAnimationFrameTiming girişi için (entry.paintTime || entry.startTime + entry.duration) - entry.styleAndLayoutStart hesaplayın).