WordPress’te Lazy Load Özelliği functions.php ile Nasıl Eklenir?

Web sitelerinin performansı söz konusu olduğunda, sayfa yükleme süresi hem kullanıcı deneyimi hem de SEO açısından kritik bir faktör. Özellikle görsel ağırlıklı WordPress sitelerinde, tüm resimlerin sayfa açılışında yüklenmesi ciddi bir performans sorunu yaratıyor. İşte bu noktada lazy load (tembel yükleme) devreye giriyor. Kullanıcı sayfayı kaydırdıkça resimlerin yüklenmesi, ilk sayfa yükleme süresini dramatik şekilde düşürüyor. Bu yazıda functions.php dosyası üzerinden WordPress’e nasıl lazy load ekleyeceğinizi, farklı senaryolara özel çözümleri ve üretim ortamında dikkat etmeniz gerekenleri ele alacağım.

Lazy Load Neden Bu Kadar Önemli?

Diyelim ki bir WooCommerce mağazanız var ve kategoriler sayfasında 48 ürün gösteriyorsunuz. Her ürünün bir görseli var ve kullanıcı sayfayı açtığı anda tüm 48 görsel aynı anda yüklenmeye çalışıyor. Kullanıcının ekran dışında kalan 40 görseli hiç görmeden sayfayı terk etmesi durumunda, o 40 görsel boşa yüklenmiş oluyor.

Google Core Web Vitals metriklerinde LCP (Largest Contentful Paint) ve FID (First Input Delay) değerlerinizi lazy load ile ciddi oranda iyileştirebilirsiniz. WordPress 5.5’ten itibaren görsellere otomatik olarak loading="lazy" atributu ekleniyor, ancak bu her zaman yeterli olmuyor. Özellikle tema editörlerinizin eklediği görseller, arka plan resimleri veya dinamik olarak yüklenen içerikler bu otomatik özelliğin dışında kalabiliyor.

WordPress Native Lazy Load’u Anlamak

WordPress 5.5 ile gelen native lazy load desteği, the_post_thumbnail() ve wp_get_attachment_image() fonksiyonları aracılığıyla eklenen görsellere otomatik olarak loading="lazy" ekliyor. Ancak bazı durumlarda bu özelliği manuel olarak kontrol etmeniz gerekiyor.

İlk kod örneğimizde, WordPress’in tüm görsellere lazy load uyguladığından emin olalım:

// functions.php
add_filter( 'wp_lazy_loading_enabled', '__return_true' );

// Belirli bir context için lazy load'u devre dışı bırakma
add_filter( 'wp_lazy_loading_enabled', function( $default, $tag_name, $context ) {
    // Header logosu lazy load olmasın
    if ( $context === 'the_logo' ) {
        return false;
    }
    return $default;
}, 10, 3 );

Bu filtre oldukça güçlü. $context parametresi sayesinde hangi görsel bağlamında lazy load’un aktif olup olmayacağını kontrol edebiliyorsunuz. Logo, hero banner gibi above-the-fold (ekranın hemen görünen kısmındaki) görsellerde lazy load kullanmak performansı olumsuz etkileyebiliyor çünkü tarayıcı bu görseli önce yükleyip sonra lazy load kuyruğuna alıyor.

LCP Görsellerinde loading=”eager” Kullanımı

Bunu sysadmin perspektifinden düşünürsek: sunucu taraflı bir kural yazıyoruz ve bu kuralın istisnalarını iyi tanımlamamız lazım. Above-the-fold görseller için loading="eager" veya fetchpriority="high" kullanmak, Google’ın önerdiği bir yaklaşım.

// Hero image veya featured image'e eager loading ekle
add_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment, $size ) {
    // Sadece belirli bir attachment ID için
    $hero_image_id = get_theme_mod( 'hero_image_id' );
    
    if ( $attachment->ID == $hero_image_id ) {
        $attr['loading']      = 'eager';
        $attr['fetchpriority'] = 'high';
        unset( $attr['decoding'] );
    }
    
    return $attr;
}, 10, 3 );

Burada wp_get_attachment_image_attributes filtresini kullanarak belirli bir görselin davranışını override ediyoruz. Bu yaklaşım, WordPress’in otomatik lazy load mekanizmasıyla çakışmıyor ve tema bağımsız çalışıyor.

İçerik Görsellerine Toplu Lazy Load Ekleme

Bazı temalar veya page builder’lar taglarına loading atributu eklemiyor. Bu durumda içerik filtreleme yöntemiyle toplu lazy load ekleyebilirsiniz:

// the_content filtresini kullanarak tüm içerik görsellerine lazy load ekle
add_filter( 'the_content', function( $content ) {
    if ( is_admin() || ! in_the_loop() ) {
        return $content;
    }
    
    // Zaten loading atributu olan görselleri atlayalım
    $content = preg_replace_callback(
        '/<img([^>]+)>/i',
        function( $matches ) {
            $img_tag = $matches[0];
            
            // Zaten loading atributu varsa dokunma
            if ( strpos( $img_tag, 'loading=' ) !== false ) {
                return $img_tag;
            }
            
            // loading="lazy" ekle
            $img_tag = str_replace( '<img', '<img loading="lazy"', $img_tag );
            return $img_tag;
        },
        $content
    );
    
    return $content;
} );

Bu yaklaşım regex tabanlı olduğu için dikkatli kullanın. Büyük içeriklerde performans etkisi olabilir, bu yüzden object cache kullanıyorsanız bu işlemin önbelleğe alındığından emin olun.

WooCommerce Ürün Görselleri için Özel Lazy Load

WooCommerce mağazalarında ürün görselleri özel bir kategori. Shop sayfasında thumbnail’lar, ürün detay sayfasında gallery görselleri ve ilgili ürünler bölümü ayrı ayrı ele alınmalı:

// WooCommerce ürün galeri görsellerine lazy load ekle
add_filter( 'woocommerce_product_get_image', function( $image, $product, $size, $attr, $placeholder, $image_url ) {
    // Eğer görsel yoksa placeholder için de lazy load ekleyelim
    if ( strpos( $image, 'loading=' ) === false ) {
        $image = str_replace( '<img', '<img loading="lazy"', $image );
    }
    return $image;
}, 10, 6 );

// WooCommerce gallery thumbnail'larına özel işlem
add_filter( 'woocommerce_gallery_image_html', function( $html ) {
    if ( strpos( $html, 'loading=' ) === false ) {
        $html = str_replace( '<img', '<img loading="lazy"', $html );
    }
    return $html;
} );

Gerçek dünya senaryosunda, müşterilerimden birinin WooCommerce mağazasında 200+ ürün galerisi görseli vardı. Lazy load eklenmeden önce shop sayfasının ilk yüklenmesi 8-12 saniye arasındaydı. Bu değişiklikten sonra 1.8 saniyeye düştü. Network tab’ını açıp kontrol ettiğinizde, sadece viewport’ta görünen görsellerin yüklendiğini göreceksiniz.

JavaScript ile Gelişmiş Lazy Load (Intersection Observer)

Native lazy load harika ama eski tarayıcı desteği veya özel animasyon efektleri istiyorsanız JavaScript tabanlı bir çözüme ihtiyacınız var. functions.php üzerinden bu script’i doğru şekilde ekleyelim:

// Intersection Observer tabanlı lazy load script'ini enqueue et
add_action( 'wp_enqueue_scripts', function() {
    $inline_script = "
    (function() {
        'use strict';
        
        var lazyImages = [];
        var lazyLoaded = false;
        
        function initLazyLoad() {
            lazyImages = [].slice.call(document.querySelectorAll('img.lazy-load'));
            
            if ('IntersectionObserver' in window) {
                var lazyImageObserver = new IntersectionObserver(function(entries) {
                    entries.forEach(function(entry) {
                        if (entry.isIntersecting) {
                            var lazyImage = entry.target;
                            lazyImage.src = lazyImage.dataset.src;
                            
                            if (lazyImage.dataset.srcset) {
                                lazyImage.srcset = lazyImage.dataset.srcset;
                            }
                            
                            lazyImage.classList.remove('lazy-load');
                            lazyImage.classList.add('lazy-loaded');
                            lazyImageObserver.unobserve(lazyImage);
                        }
                    });
                }, {
                    rootMargin: '200px 0px',
                    threshold: 0.01
                });
                
                lazyImages.forEach(function(lazyImage) {
                    lazyImageObserver.observe(lazyImage);
                });
            }
        }
        
        document.addEventListener('DOMContentLoaded', initLazyLoad);
    })();
    ";
    
    wp_add_inline_script( 'jquery', $inline_script );
} );

rootMargin: '200px 0px' değeri kritik. Görsel viewport’a 200px kala yüklenmeye başlıyor, bu sayede kullanıcı kaydırırken boş görsel alanı görmüyor. Bu değeri bağlantı hızına göre dinamik olarak da ayarlayabilirsiniz.

CSS ile Blur-Up Efekti Eklemek

Sadece lazy load yetmez, kullanıcı deneyimini daha da iyileştirmek için görsel yüklenirken blur efekti gösterebilirsiniz. Bu teknik Medium ve diğer büyük sitelerde yaygın olarak kullanılıyor:

// Lazy load CSS ve placeholder stillerini ekle
add_action( 'wp_head', function() {
    ?>
    <style>
    img.lazy-load {
        filter: blur(10px);
        transition: filter 0.3s ease-in-out;
        background-color: #f0f0f0;
    }
    
    img.lazy-loaded {
        filter: blur(0);
    }
    
    /* Aspect ratio placeholder - layout shift önleme */
    .img-wrapper {
        position: relative;
        overflow: hidden;
    }
    
    .img-wrapper img {
        width: 100%;
        height: auto;
        display: block;
    }
    </style>
    <?php
} );

Bu CSS’i inline eklemek önemli. Eğer ayrı bir CSS dosyasına koyarsanız, stil dosyası yüklenmeden önce görüntüler render edilebilir ve anlık bir parıldama (flash) efekti oluşabilir.

Avatar ve Yorum Görsellerine Lazy Load

Blog yazılarında yorum bölümü yüzlerce avatar görseli içerebilir. Bunları da lazy load kapsamına alalım:

// Yorum avatar'larına lazy load ekle
add_filter( 'get_avatar', function( $avatar, $id_or_email, $size, $default, $alt, $args ) {
    // Admin arayüzünde değişiklik yapma
    if ( is_admin() ) {
        return $avatar;
    }
    
    // data-src pattern'ine çevir
    $avatar = preg_replace( '/src=(["'])(.+?)1/', 'src=$1data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7$1 data-src=$1$2$1', $avatar );
    $avatar = str_replace( 'class='avatar', 'loading="lazy" class='avatar lazy-load', $avatar );
    
    return $avatar;
}, 10, 6 );

Burada base64 encoded 1×1 pixel transparent GIF kullanıyoruz. Bu sayede src atributu boş kalmıyor ve tarayıcı hata vermiyor. Gerçek kaynak data-src içinde tutuluyor.

Conditional Loading: Sadece Gerektiğinde Aktif Et

Lazy load her sayfada gerekli olmayabilir. Admin panelinde, RSS feed’de veya print sayfasında gereksiz. Bunu akıllıca yönetelim:

// Sadece frontend ve gerekli koşullarda lazy load aktif et
function mytheme_should_lazy_load() {
    // Admin panelinde hayır
    if ( is_admin() ) {
        return false;
    }
    
    // RSS feed'de hayır
    if ( is_feed() ) {
        return false;
    }
    
    // REST API isteklerinde hayır
    if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
        return false;
    }
    
    // WP-CLI komutlarında hayır
    if ( defined( 'WP_CLI' ) && WP_CLI ) {
        return false;
    }
    
    // AMP sayfalarında hayır (AMP kendi lazy load mekanizmasını kullanır)
    if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
        return false;
    }
    
    return true;
}

// Ana lazy load fonksiyonunu conditional wrapper'a al
add_filter( 'the_content', function( $content ) {
    if ( ! mytheme_should_lazy_load() ) {
        return $content;
    }
    
    // Lazy load işlemleri buraya
    return $content;
} );

Bu yaklaşım production ortamında hayat kurtarıyor. Özellikle WP-CLI ile toplu işlem yapıyorsanız veya headless WordPress kullanıyorsanız, lazy load kodunun devreye girmesi istenmeyen sonuçlar doğurabilir.

Performance Debugging: Lazy Load Çalışıyor mu?

Kurulumu yaptıktan sonra gerçekten çalışıp çalışmadığını doğrulamak için birkaç yöntem var:

Chrome DevTools Network Tab kullanımı:

  • Sayfa açıkken Network sekmesini açın
  • Sadece “Img” filtresini seçin
  • Sayfayı yenileyin ve kaç görsel yüklendiğini not edin
  • Sayfayı aşağı kaydırın ve yeni görsellerin network tab’a eklendiğini gözlemleyin

Quick PHP debug snippet:

// Geçici debug - production'da kaldırın!
add_action( 'wp_footer', function() {
    if ( ! current_user_can( 'administrator' ) ) {
        return;
    }
    
    global $wpdb;
    $image_count = $wpdb->get_var(
        "SELECT COUNT(*) FROM {$wpdb->postmeta} 
         WHERE meta_key = '_thumbnail_id'"
    );
    
    echo "<!-- Lazy Load Debug: Toplam featured image sayisi: {$image_count} -->";
    echo "<!-- WordPress lazy load filter aktif: " . ( has_filter( 'wp_lazy_loading_enabled' ) ? 'EVET' : 'HAYIR' ) . " -->";
} );

Bu snippet’i geliştirme ortamında kullanabilirsiniz. HTML kaynak kodunu incelediğinizde bu yorumları göreceksiniz.

Caching ile Entegrasyon

Lazy load ve caching birlikte düşünülmesi gereken konular. WP Rocket, W3 Total Cache veya LiteSpeed Cache kullanıyorsanız, bunların kendi lazy load mekanizmaları var. İki lazy load sisteminin aynı anda çalışması sorun yaratabilir.

// WP Rocket'ın lazy load'u ile çakışmayı önle
add_filter( 'wp_lazy_loading_enabled', function( $enabled ) {
    // WP Rocket aktifse kendi lazy load'una bırak
    if ( defined( 'WP_ROCKET_VERSION' ) ) {
        return false;
    }
    
    // LiteSpeed Cache aktifse
    if ( defined( 'LSCWP_V' ) ) {
        return false;
    }
    
    return $enabled;
} );

Bu kontrolü yapmadan çift lazy load aktifleştirirseniz, görseller bazen hiç yüklenmeyebilir veya iki kez yükleme girişiminde bulunabilir.

Mobil Optimizasyon için Bant Genişliği Kontrolü

Modern tarayıcılar Navigator.connection API’si sayesinde kullanıcının bağlantı hızına erişebiliyor. Bu bilgiyi kullanarak lazy load davranışını dinamik olarak ayarlayabilirsiniz:

// Bağlantı hızına göre lazy load agresifliğini ayarla
add_action( 'wp_head', function() {
    ?>
    <script>
    (function() {
        var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
        
        if (connection) {
            var effectiveType = connection.effectiveType;
            
            // Yavaş bağlantıda daha agresif lazy load
            if (effectiveType === '2g' || effectiveType === 'slow-2g') {
                document.documentElement.classList.add('slow-connection');
                // Tüm görsellere lazy load uygula, none=eager olsun
                document.addEventListener('DOMContentLoaded', function() {
                    var allImages = document.querySelectorAll('img:not([loading])');
                    allImages.forEach(function(img) {
                        img.setAttribute('loading', 'lazy');
                    });
                });
            }
        }
    })();
    </script>
    <?php
} );

Sonuç

WordPress’te lazy load eklemek göründüğünden çok katmanlı bir konu. functions.php üzerinden yapabileceğiniz işlemler şunlar:

  • Native WordPress lazy load’u kontrol etmek: wp_lazy_loading_enabled filtresiyle açıp kapatabilirsiniz
  • Above-the-fold görselleri korumak: wp_get_attachment_image_attributes filtresiyle LCP görsellerine eager loading atayabilirsiniz
  • İçerik görsellerini toplu işlemek: the_content filtresiyle regex tabanlı atribut ekleme yapabilirsiniz
  • WooCommerce entegrasyonunu sağlamak: WooCommerce’e özel filtrelerle ürün ve galeri görsellerini kapsama alabilirsiniz
  • Caching eklentileriyle çakışmayı önlemek: Koşullu kontroller sayesinde çift lazy load sorununu engelleyebilirsiniz

Benim önerim şu: Eğer WP Rocket veya benzeri bir premium caching eklentisi kullanıyorsanız, lazy load için o eklentinin mekanizmasına güvenin. Eğer manuel bir setup yapıyorsanız, native loading="lazy" atributunu temel alın ve üstüne JavaScript tabanlı Intersection Observer ekleyin. Bu kombinasyon hem performanslı hem de geniş tarayıcı desteği sunuyor.

Son olarak, yaptığınız değişikliklerden sonra Google PageSpeed Insights ve WebPageTest ile ölçüm yapın. Rakamlar sizi şaşırtacak.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir