Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Intersection Observer API ile sadece görünür alandaki component'ları render ederek ilk sayfa yükünü nasıl hafiflettiğim

✖ Kapat
Duyuru
✖ Kapat
Duyuru

webnix

Üye
Katılım
14 Mart 2026
Mesajlar
52
Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorunu ve onun en temiz çözümünü anlatacağım. Projemde, ana sayfada kullanıcıyı selamlayan devasa bir "hero" bölümü, ardından yüzlerce ürün kartı ve en sonunda da ağır yorum bileşenleri vardı. Sayfa ilk açıldığında, kullanıcı henüz görmediği ve belki de hiç kaydırıp görmeyeceği tüm bu component'lar DOM'a yükleniyor, bundle boyutu şişiyor ve Lighthouse performans skoru yerlerde sürünüyordu. İşte tam burada Intersection Observer API imdadıma yetişti.

🔥 Sorunun Tam Olarak Nerede Olduğunu Anlamak

Sorun şuydu: Kullanıcı sadece ilk ekranda gördüğü içerikle etkileşime geçmek istiyordu ama tarayıcı, sayfanın en altındaki yorum bileşeninin CSS'sini, JS'ini ve resimlerini de indirip işliyordu. Bu, özellikle mobilde ve düşük performanslı cihazlarda ciddi bir gecikmeye neden oluyordu. "Acaba tüm bu içeriği lazy loading ile mi ayırsam?" diye düşünürken, daha native ve modern bir çözüm olan Intersection Observer'ı keşfettim.

⚙️ Intersection Observer Nedir ve Nasıl Çalışır?

Kısaca, bu API bize bir DOM elementinin viewport (görünür alan) ile kesişimini izleme imkanı veriyor. Yani bir div, viewport'a girdiği veya çıktığı anda bizi haberdar edebiliyor. Bu özelliği kullanarak, bir component'ı sadece görünür olacağı zaman DOM'a inject edebilir veya render ettirebiliriz.

İşte React projemde kullandığım temel bir hook yapısı:

JavaScript:
import { useEffect, useRef, useState } from 'react';

const useLazyLoad = (options = {}) => {
  const containerRef = useRef(null);
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      // Element görünür olduğunda state'i güncelle
      if (entry.isIntersecting) {
        setIsVisible(true);
        // Gerekirse gözlemi durdur (sadece bir kere yüklemek için)
        observer.unobserve(entry.target);
      }
    }, options);

    if (containerRef.current) {
      observer.observe(containerRef.current);
    }

    return () => {
      if (containerRef.current) {
        observer.unobserve(containerRef.current);
      }
    };
  }, [options]);

  return [containerRef, isVisible];
};

export default useLazyLoad;

💡 Hook'u Component'larda Nasıl Kullandım?

Artık elimde sihirli bir hook var. Ağır olan ve ilk görünümde gerekli olmayan her component'ı bu hook ile sarmalayabilirim. İşte bir ürün listesi component'ı örneği:

JavaScript:
import React, { Suspense } from 'react';
import useLazyLoad from './hooks/useLazyLoad';
import ProductCardSkeleton from './ProductCardSkeleton';

// Ağır bileşeni lazy import ediyoruz
const HeavyProductCard = React.lazy(() => import('./HeavyProductCard'));

const ProductList = ({ products }) => {
  const [containerRef, isVisible] = useLazyLoad({
    rootMargin: '100px', // Viewport'a 100px kala tetikle
  });

  return (
    <div ref={containerRef}>
      {isVisible ? (
        <Suspense fallback={<ProductCardSkeleton />}>
          {products.map(product => (
            <HeavyProductCard key={product.id} data={product} />
          ))}
        </Suspense>
      ) : (
        // Henüz görünmüyorsa, yer tutucu (skeleton) göster
        <ProductCardSkeleton count={3} />
      )}
    </div>
  );
};

export default ProductList;

Bu yapıda, HeavyProductCard component'ı ve onun içerdiği tüm modüller (resimler, ikon kütüphaneleri vs.), kullanıcı o bölüme yaklaşana kadar yüklenmiyor. rootMargin ile biraz daha erken tetikleyip, yükleme sırasında oluşabilecek boşluk hissini de azaltabilirsiniz.

📈 Elde Ettiğim Sonuçlar ve Çıkarımlar

Bu tekniği sayfanın alt bölümlerindeki yorumlar, önerilen ürünler ve sosyal medya feed'leri gibi alanlara uyguladıktan sonra, ilk sayfa yükünde gözle görülür bir iyileşme oldu. First Contentful Paint (FCP) ve Largest Contentful Paint (LCP) metriklerim ciddi oranda düzeldi. En güzeli de, kullanıcı deneyiminden hiç ödün vermemiş olmam. Onlar kaydırdıkça içerik sihirli bir şekilde beliriyor.

Siz de projelerinizde böyle bir performans sorunu yaşadınız mı? Intersection Observer dışında, React Virtual List veya farklı lazy loading kütüphaneleri deneyen oldu mu? Deneyimlerinizi yorumlarda paylaşırsanız çok sevinirim. Bir sonraki yazıda görüşmek üzere, kodla kalın!
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri