İçeriğe geç
Performance

Third-Party Script Yönetimi: Performans Etkisi ve Çözümler

Tarık Tunç
Third-Party Script Yönetimi: Performans Etkisi ve Çözümler

Third-Party Script Yönetimi: Performans Etkisi ve Çözümler

Üçüncü parti scriptler — analytics, reklam, chat widget'ları, sosyal medya entegrasyonları — modern web sitelerinin vazgeçilmez parçalarıdır. Ancak HTTP Archive verilerine göre ortalama bir web sitesi 20'den fazla üçüncü parti script yükler ve bu scriptler toplam JavaScript boyutunun %50'sinden fazlasını oluşturur. Bu rehberde üçüncü parti scriptlerin performans etkisini ölçmeyi, kontrol altına almayı ve en iyi yükleme stratejilerini uygulamayı öğreneceksiniz.

Üçüncü Parti Scriptlerin Performans Etkisi

Third-party scriptler performansı birden fazla boyutta etkiler:

  • Ağ etkisi: Ek DNS çözümleme, TCP/TLS bağlantıları ve bant genişliği kullanımı
  • CPU etkisi: Parse, compile ve execution süresi ana thread'i bloke eder
  • Render etkisi: DOM manipülasyonu, layout thrashing ve forced reflow
  • CLS etkisi: Dinamik olarak eklenen içerik (reklam, chat widget) layout kaymalarına neden olur
  • Güvenlik etkisi: XSS riski, veri sızıntısı, supply chain saldırıları
Bilgi: Google'ın araştırmasına göre, üçüncü parti scriptler ortalama bir sayfanın TBT (Total Blocking Time) metriğinin %57'sinden sorumludur. Bir chat widget'ı tek başına 500KB+ JavaScript yükleyebilir.

Üçüncü Parti Script Etkisini Ölçme

Performans etkisini ölçmek, optimizasyonun ilk adımıdır. Chrome DevTools ve Lighthouse bu konuda güçlü araçlar sunar:

// Performance Observer ile third-party script süresini ölç
const thirdPartyOrigins = [
  'www.google-analytics.com',
  'www.googletagmanager.com',
  'connect.facebook.net',
  'platform.twitter.com',
  'cdn.jsdelivr.net'
];

function isThirdParty(url) {
  try {
    const origin = new URL(url).hostname;
    return !origin.includes(window.location.hostname);
  } catch {
    return false;
  }
}

// Resource timing ile yükleme süresini analiz et
function analyzeThirdPartyImpact() {
  const resources = performance.getEntriesByType('resource');

  const thirdParty = resources.filter(r => isThirdParty(r.name));
  const firstParty = resources.filter(r => !isThirdParty(r.name));

  const tpTotalSize = thirdParty.reduce((sum, r) => sum + r.transferSize, 0);
  const tpTotalTime = thirdParty.reduce((sum, r) =>
    sum + (r.responseEnd - r.startTime), 0);

  console.table({
    'Üçüncü Parti': {
      'Sayı': thirdParty.length,
      'Toplam Boyut': `${(tpTotalSize / 1024).toFixed(1)} KB`,
      'Toplam Süre': `${tpTotalTime.toFixed(0)} ms`
    },
    'Birinci Parti': {
      'Sayı': firstParty.length,
      'Toplam Boyut': `${(firstParty.reduce((s, r) =>
        s + r.transferSize, 0) / 1024).toFixed(1)} KB`,
      'Toplam Süre': `${firstParty.reduce((s, r) =>
        s + (r.responseEnd - r.startTime), 0).toFixed(0)} ms`
    }
  });
}

window.addEventListener('load', () => {
  setTimeout(analyzeThirdPartyImpact, 3000);
});

Yükleme Stratejileri

Üçüncü parti scriptlerin yükleme zamanlamasını kontrol etmek, performans etkisini minimize etmenin en etkili yoludur:

<!-- 1. Kritik olmayan scriptleri user interaction sonrası yükle -->
<script>
// Chat widget'ı: Sayfa yüklenip kullanıcı etkileşime geçtikten sonra yükle
function loadChatWidget() {
  const script = document.createElement('script');
  script.src = 'https://chat-provider.com/widget.js';
  script.async = true;
  document.head.appendChild(script);
}

// İlk etkileşimde yükle
const events = ['mousedown', 'touchstart', 'scroll', 'keydown'];
const loadOnInteraction = () => {
  loadChatWidget();
  events.forEach(e => document.removeEventListener(e, loadOnInteraction));
};
events.forEach(e => document.addEventListener(e, loadOnInteraction, { once: true }));

// Veya idle callback ile
if ('requestIdleCallback' in window) {
  requestIdleCallback(loadChatWidget, { timeout: 5000 });
}
</script>

<!-- 2. Analytics: async ile yükle (sıra önemli değil) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"></script>

<!-- 3. Facade pattern: Ağır widget yerine hafif placeholder -->
<!-- YouTube embed yerine statik thumbnail göster -->
<div class="youtube-facade" data-video-id="dQw4w9WgXcQ"
    >
  <img src="/images/youtube-thumb.webp" alt="Video başlığı"
       loading="lazy" width="560" height="315">
  <button class="play-button" aria-label="Videoyu oynat">▶</button>
</div>
İpucu: Facade pattern, YouTube embed (~800KB), Google Maps (~700KB) ve sosyal medya widget'ları için çok etkilidir. Kullanıcı etkileşime geçene kadar statik bir görsel gösterin, tıklandığında gerçek widget'ı yükleyin. Bu, ilk yükleme süresini saniyeler düzeyinde iyileştirebilir.

Google Tag Manager Optimizasyonu

GTM, birden fazla üçüncü parti scripti merkezi olarak yönetmenizi sağlar. Ancak yanlış konfigürasyon performansı ciddi şekilde etkileyebilir:

// GTM optimizasyon stratejileri

// 1. GTM'i async yükle (zaten varsayılan)
// 2. Trigger'ları optimize et - DOM Ready yerine Window Loaded kullan
// 3. Tag firing priority ile kritik tagları önce çalıştır

// Server-side GTM: Script yükünü sunucuya taşı
// Client-side: 1 GTM scripti yükle → 10+ tag tetiklenir
// Server-side: 1 GTM scripti yükle → sunucu tarafında işlenir

// Partytown ile main thread dışında çalıştırma
// Third-party scriptleri Web Worker'a taşır
<!-- Partytown ile third-party scriptleri Web Worker'da çalıştır -->
<script>
  // Partytown konfigürasyonu
  partytown = {
    forward: ['dataLayer.push', 'gtag'],
    resolveUrl: (url) => {
      // Proxy üzerinden yükle (CORS sorunlarını çözer)
      if (url.hostname === 'www.google-analytics.com') {
        return new URL('/proxy' + url.pathname, window.location.origin);
      }
      return url;
    }
  };
</script>
<script src="/~partytown/partytown.js"></script>

<!-- type="text/partytown" ile script Worker'da çalışır -->
<script type="text/partytown" src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"></script>
<script type="text/partytown">
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXX');
</script>
Uyarı: Partytown Web Worker'da DOM erişimi Proxy ile sağlar ve bazı kısıtlamaları vardır. Tüm scriptler Worker'da sorunsuz çalışmayabilir. Production'a almadan önce kapsamlı test yapın. Özellikle DOM'a yoğun erişen scriptler (chat widget'ları, overlay'ler) sorunlu olabilir.

Content Security Policy (CSP) ile Güvenlik

CSP header'ları ile hangi domain'lerden script yükleneceğini kısıtlayarak güvenlik ve kontrol sağlayın:

# Content-Security-Policy header
Content-Security-Policy:
  default-src 'self';
  script-src 'self'
    https://www.googletagmanager.com
    https://www.google-analytics.com
    'nonce-{random}';
  connect-src 'self'
    https://www.google-analytics.com
    https://api.example.com;
  img-src 'self' data: https:;
  style-src 'self' 'unsafe-inline';
  font-src 'self' https://fonts.gstatic.com;

Third-Party Audit Kontrol Listesi

  1. Lighthouse "Third-party usage" denetimini çalıştırın
  2. Her üçüncü parti scriptin iş değerini sorgulayın — kullanılmıyorsa kaldırın
  3. Kritik olmayanları lazy load edin (user interaction veya idle callback)
  4. Facade pattern uygulayın (YouTube, Maps, sosyal widget)
  5. Preconnect ile bağlantı süresini azaltın
  6. Subresource Integrity (SRI) ile bütünlüğü doğrulayın
  7. CSP ile izin verilen domain'leri kısıtlayın
  8. Düzenli olarak bundle boyutunu ve performans etkisini izleyin

Sonuç

Üçüncü parti scriptler iş gereksinimlerini karşılarken performansı önemli ölçüde etkileyebilir. Her scriptin etkisini ölçün, kritik olmayanları erteleyerek yükleyin, facade pattern ile ağır widget'ları hafifletin ve Partytown gibi araçlarla ana thread'i koruyun. Düzenli audit ile gereksiz scriptleri temizleyin ve CSP ile güvenliği sağlayın.

Kaynaklar

İlgili Yazılar