Merhaba arkadaşlar, bugün sizlere başlangıçta benim de kafamı karıştıran, sayfa performansını doğrudan etkileyen bir konudan bahsedeceğim. Script etiketlerindeki `defer` ve `async` özellikleri. Bu ikisini yanlış kullandığımda sayfa yüklenmesi aniden yavaşlıyor veya bazı fonksiyonlar çalışmıyordu. İşte bu sancılı süreçten sonra oturttuğum karar matrisimi sizinle paylaşacağım.
Karşılaştığım Sorun
Bir projede, sayfanın en altına eklediğim harici bir analytics script'i vardı. Sayfa hızlı yüklensin diye bu script'e `async` ekledim. Ancak bir süre sonra, bu script'e bağımlı olan ve DOM'u manipüle eden bir başka script'im çalışmamaya başladı. Kafayı yemiştim! Sebep, `async`'in script'i indirir indirmez, henüz DOM tamamen oluşmadan çalıştırması ve diğer script'in ihtiyaç duyduğu elemanları bulamamasıydı. İşte o an bu iki attribute'ün derinlemesine farkını anlamam gerektiğini fark ettim.
Temel Farklar: Defer vs Async
İkisi de script'in sayfa ayrıştırılmasını (parsing) bloklamasını engeller. Yani tarayıcı `<script>` etiketine gelince durmaz, devam eder. Ama sonrası farklı.
`async` özelliği, script'i indirirken sayfa ayrıştırmasını durdurmaz. Script indirilir indirilmez, ayrıştırmayı durdurur[/COLOR], scripti çalıştırır, sonra kaldığı yerden devam eder. Sırası belli değildir, kim önce inerse o çalışır.
`defer` özelliği de ayrıştırmayı durdurmaz. Ancak script, sayfanın ayrıştırılması tamamen bittikten sonra (DOMContentLoaded event'inden önce) ve belgeye yazıldığı sırayla çalıştırılır.
Aradaki temel farkı gösteren basit bir örnek paylaşayım:
Hangi Durumda Hangisini Kullanıyorum? (Karar Matrisim)
Artık her yeni script eklerken kendime şu soruları soruyorum:
1. Bu script, sayfanın DOM yapısına ihtiyaç duyuyor mu? (Örn: jQuery, DOM manipülasyonu yapan kodlar)
Evet -> defer kullan. DOM hazır olmadan çalışmasın.
2. Bu script, diğer script'lere bağımlı mı? Veya diğer script'ler buna bağımlı mı? (Örn: önce kütüphane (jQuery), sonra eklentisi)
Evet -> defer kullan ve sıralamayı doğru yap. Sıra önemli.
3. Bu script tamamen bağımsız ve mümkün olan en kısa sürede çalışması kritik mi? (Örn: sayacı, reklam script'i, bazı analytics'ler)
Evet -> async kullan. "İndirildiği an" çalışsın.
4. Script çok küçük ve kritik mi? (Örn: sayfanın ilk anında ihtiyaç duyulan bir polyfill)
Evet -> Hiçbirini kullanma, script'i `<head>` içinde inline yaz. Veya kritik yolun bir parçası yap.
Bu mantığı bir kod üzerinde görelim:
Son Söz ve Performans İpucu
Genel kuralım şu: Eğer emin değilseniz, default olarak `defer` kullanın. Çünkü DOM hazır olmadan çalışmayacağı için daha güvenli. `async` ise daha agresif bir performans optimizasyonudur, ancak bağımlılıkları bozma riski taşır.
Modern uygulamalarda (React, Vue) build tool'ları (Webpack, Vite) genellikle bu attribute'leri sizin için otomatik ekler ve chunk'ları optimize eder. Ama temel HTML sayfalarınıza harici script eklerken bu matrisi düşünmeniz, bir sürü gizli hatadan kurtaracaktır.
Siz bu iki attribute'ü kullanırken hangi senaryolarda hangi tuzağa düştünüz? Veya farklı bir karar mekanizmanız var mı? Yorumlarda paylaşalım!
Bir projede, sayfanın en altına eklediğim harici bir analytics script'i vardı. Sayfa hızlı yüklensin diye bu script'e `async` ekledim. Ancak bir süre sonra, bu script'e bağımlı olan ve DOM'u manipüle eden bir başka script'im çalışmamaya başladı. Kafayı yemiştim! Sebep, `async`'in script'i indirir indirmez, henüz DOM tamamen oluşmadan çalıştırması ve diğer script'in ihtiyaç duyduğu elemanları bulamamasıydı. İşte o an bu iki attribute'ün derinlemesine farkını anlamam gerektiğini fark ettim.
İkisi de script'in sayfa ayrıştırılmasını (parsing) bloklamasını engeller. Yani tarayıcı `<script>` etiketine gelince durmaz, devam eder. Ama sonrası farklı.
`async` özelliği, script'i indirirken sayfa ayrıştırmasını durdurmaz. Script indirilir indirilmez, ayrıştırmayı durdurur[/COLOR], scripti çalıştırır, sonra kaldığı yerden devam eder. Sırası belli değildir, kim önce inerse o çalışır.
`defer` özelliği de ayrıştırmayı durdurmaz. Ancak script, sayfanın ayrıştırılması tamamen bittikten sonra (DOMContentLoaded event'inden önce) ve belgeye yazıldığı sırayla çalıştırılır.
Aradaki temel farkı gösteren basit bir örnek paylaşayım:
HTML:
<!DOCTYPE html>
<html>
<head>
<!-- ASYNC: Sırası belli değil, belki 2.js önce çalışır -->
<script src="1.js" async></script>
<script src="2.js" async></script>
</head>
<body>
<!-- DEFER: Kesinlikle 3.js, 4.js'den önce çalışır -->
<script src="3.js" defer></script>
<script src="4.js" defer></script>
</body>
</html>
Artık her yeni script eklerken kendime şu soruları soruyorum:
1. Bu script, sayfanın DOM yapısına ihtiyaç duyuyor mu? (Örn: jQuery, DOM manipülasyonu yapan kodlar)
Evet -> defer kullan. DOM hazır olmadan çalışmasın.
2. Bu script, diğer script'lere bağımlı mı? Veya diğer script'ler buna bağımlı mı? (Örn: önce kütüphane (jQuery), sonra eklentisi)
Evet -> defer kullan ve sıralamayı doğru yap. Sıra önemli.
3. Bu script tamamen bağımsız ve mümkün olan en kısa sürede çalışması kritik mi? (Örn: sayacı, reklam script'i, bazı analytics'ler)
Evet -> async kullan. "İndirildiği an" çalışsın.
4. Script çok küçük ve kritik mi? (Örn: sayfanın ilk anında ihtiyaç duyulan bir polyfill)
Evet -> Hiçbirini kullanma, script'i `<head>` içinde inline yaz. Veya kritik yolun bir parçası yap.
Bu mantığı bir kod üzerinde görelim:
HTML:
<head>
<!-- Bağımsız ve hızlı çalışsın: ASYNC -->
<script src="https://analytics.example.com/script.js" async></script>
<!-- DOM'a ihtiyacı var, sıra önemli: DEFER -->
<script src="assets/js/vendor/jquery.min.js" defer></script>
<script src="assets/js/plugins/slider.js" defer></script> <!-- jQuery'ye bağımlı -->
<script src="assets/js/main.js" defer></script> <!-- Tüm DOM'a ve plugin'lere bağımlı -->
</head>
Genel kuralım şu: Eğer emin değilseniz, default olarak `defer` kullanın. Çünkü DOM hazır olmadan çalışmayacağı için daha güvenli. `async` ise daha agresif bir performans optimizasyonudur, ancak bağımlılıkları bozma riski taşır.
Modern uygulamalarda (React, Vue) build tool'ları (Webpack, Vite) genellikle bu attribute'leri sizin için otomatik ekler ve chunk'ları optimize eder. Ama temel HTML sayfalarınıza harici script eklerken bu matrisi düşünmeniz, bir sürü gizli hatadan kurtaracaktır.
Siz bu iki attribute'ü kullanırken hangi senaryolarda hangi tuzağa düştünüz? Veya farklı bir karar mekanizmanız var mı? Yorumlarda paylaşalım!