Aslında back-end 🔩 tarafında kod yazdığım için javascript dilinde, temelleri 🎯 ve çok bilinen frameworkleri dışında şahsen öyle aman aman bir bilgim ve kullanımım yok. Gerçi yıllar önce Chrome V8 engine bu durumu tepetaklak etti. Tarayıcıya ihtiyaç duymadan sunucu tarafına da müdahale ettiği için bir backend dili olmaya doğru evrildi. Yanı sıra implements
, interface
, instanceof
, private
, public
gibi aşina olunan erişim belirleyicileri revize edilmiş durumda. Bu yüzden bence 'hybrid' bir dil haline geldi.
Yani js uzun süre daha yerini koruyacağa benziyor. Bu yüzden bugün çok işe yarar püf noktalarının birinden bahsetmek istiyorum. 'External' kullanımlar için yani <script src="script.js" />
ya da <script src="//google.com/script.js"/>
gibi domain dışında bir kullanımda geçilebilecek iki argümandan bahsedeceğim: async
ve defer
. Aslında bilindik js frameworkler bahsedeceğim işlemleri optimize ediyorlar; ancak özellikle diğer 3.parti kütüphanelerin kullanımı veya özellikle vanilla.js yazarken bu kullanımların önemi ortaya çıkar. Aslında bu iki attribute tarayıcıların kodları 'execute' etme şeklini kısmen değiştiriyor. Bu yazıda javascript nasıl çalışır, statik olmayan bir sayfa 'nasıl ayağa kalkar', DOM manipulation nedir gibi konulara değinmeyeceğim. Gereksiz yere akıl karıştırmak ve yazıyı şişirmek istemiyorum. Ama bunları araştırmanızı tavsiye ederim.
Şu an için bu iki attribute inline kullanılırsa derleyici herhangi bir hata vermez ancak HTML parse veya scriptler için bir etkisi olmaz.
Önce bu iki argüman kullanılmadan sayfanın nasıl ilerlediğine bakalım.
<script>
Aşağıdaki grafikte göreceğiniz gibi script etiketi ile karşılaşılana kadar HTML parse edilmeye devam edilir; ancak etiketle karşılaşılınca parse işlemi bloklanır ve script indirilerek çalıştırılmaya başlanır.
Günümüzün modern web uygulamalarında script dosyaları HTML satırlarından daha yüklü satırlar içerdiği için boyutları çok daha fazladır. Bu yüzden eskiye nazaran, kendi alan adınız ya da 3.parti bir script dosyasının indirilerek işlenmesi daha uzun sürer. Normalde tarayıcı HTML elementlerini yüklerken <script src="... />
gördüğü satırda dosyanın indirilmesini bekler ancak script indirilip çalıştırıldıktan sonra sayfanın geri kalanını parse etmeye devam edebilir. Yani script etiketinden sonraki tüm satırlar bloklanır. Bu, temelde iki önemli soruna yol açar.
- Sayfada script dosyasından sonraki DOM elementleri ile ilgili bir işlem yapılamaz.
- Eğer script boyutu çok büyükse sayfa yüklenene kadar HTML bloklanacaktır.
<!doctype html>
<body>
<p id="first-p">Bu satır script tagından önce</p>
<script src="script.js" />
<!-- Bu satır script dosyası yüklenene kadar gözükmez -->
<p id="second-p">Bu satır script tagından sonra</p>
</body>
Bu sorun window.onload
event'e function geçilerek ya da script sayfanın en altına eklenerek aşılmaya çalışılır. Fakat HTML parse işleminin nispeten uzun sürdüğü durumlarda da ilgili fonksiyon çıktısı için önce HTML'in tüm işinin bitirilmesini DOMContentLoaded
event bekleyecektir. Yani yapılan bu işlem, sorunun temelini çözmekten uzaktır. Hızlı bağlantılarda sorun çok fark edilmeyebilir ama özellikle yavaş hızlarda bu olay çok fazla göze batar hale gelir.
<script defer>
Bu attribute tarayıcıya script etiketini görse de HTML okumaya devam etmesini bildirir. Aynı sırada script dosyası arka planda indirilir ve HTML tamamen oluşurulduğunda çalışır. Yukarıdaki örneği defer
ile deneyelim.
<!doctype html>
<body>
<p id="first-p">Bu satır script tagından önce</p>
<script defer src="script.js" />
<!-- Bu satır script dosyasını beklemeden görünür hale gelecektir-->
<p id="second-p">Bu satır script tagından sonra</p>
</body>
- Sayfa bloklanmadan HTML işlenmeye devam eder.
- Script dosyası, DOM hazır olduğunda,
DOMContentLoaded
event öncesinde çalıştırılır.
<!doctype html>
<body>
<p id="first-p">Bu satır script tagından önce</p>
<script>
document.addEventListener('DOMContentLoaded', () => console.log("defer sonrası hazır DOM"));
</script>
<script defer src="script.js" />
<!-- Bu satır script dosyasını beklemeden görünür hale gelecektir-->
<p id="second-p">Bu satır script tagından sonra</p>
</body>
Bu örnekte de sayfa bloklanmadan görünür. DOMContentLoaded
event handler defer
attribute ile işaretlenmiş olan script dosyasını bekler. Bu dosya indirilip çalıştırıldıkdan sonra tetiklenecektir.
Ayrıca bu attribute kullanan farklı external dosyalar normal sıralarını koruyarak işleme alınır ki bu da çok işe yarar bir durumdur. Modern tarayıcılar, performans için tüm sayfayı tarayarak script etiketlerini aynı anda indirmeye başlarlar ve script dosyaları birbirini bloklamadan işlemlerine devam edecektir. Ancak defer
kullanımı; tarayıcıya dosyanın HTML'i bloklamamasını bildirmenin dışında, dosyaların normal sırasını da koruması gerektiğini bildirir.
<script defer src="long.js" />
<script defer src="small.js" />
Yani yukarıdaki örnekte önce long.js
, daha sonra small.js
indirilecektir. Eğer defer
kullanmasaydık small.js
alt satırda olmasına rağmen boyutu daha küçük olduğu için daha erken indirilecek ve eğer long.js
içinde kullanacağı bir component varsa hata verecektir.
<script async>
defer
ile benzer şekilde bu attribute kullananan script etiketleri HTML'i bloklamaz.- Diğer script dosyaları
async
ile işaretlenen scriptleri beklemediği gibiasync
ile işaretlenen scrpitler de diğerlerini beklemez. DOMContentLoaded
event veasync
scriptler de birbirlerini beklemez. Eventasync
dosyasından önce de sonra da tetiklenebilir. Yaniasync
script boyutu ile ters orantılı olarak çalışır.- Sayfa içeriği
async
ile HTML bloklanmadan görünür kalacaktır. DomContentLoaded
event öncesi veya sonrası işleme alınabilir. Yine aynı şekilde büyük boyutlu dosya eğer tarayıcıda önbelleklenmiş ise; örneğin ilk çalıştırmadasmall.js
ikinci çalıştırmadalong.js
önce çalışır. Haliyle hangisinin önce olacağı ile ilgili kesin bir garantisi yoktur. Eee nolmuş yani ne farkeder ki 😄 Fark şu; 1 saniye arayla yaptığınız iki test tamamen farklı da çıkabilir, aynı da çıkabilir. Bu aslında javascript özelinde değil; asenkron programlamayla az-çok uğraştığınızda, eğer düzgün bir yapı kurmazsanız çalışma sürelerine göre iş parçacıklarının nasıl birbirine girerek insanı delirtebilecek hale gelmesiyle ilgili bence. 😵 O yüzden benzer işlemlerde geliştirme konsolunda Network > Disable cache şekilde çalışmak mantıklı olacaktır.
Yani async
attribute kullanıldığında HTML bloklanmaz fakat defer
gibi HTML oluşmasını beklemeden aynı anda asenkron şekilde script dosyasını da indirecektir.
<!doctype html>
<body>
<p id="first-p">Bu satır script etiketinden önce</p>
<script>
document.addEventListener('DOMContentLoaded', () => console.log("defer sonrası hazır DOM"));
</script>
<script async src="long.js" />
<script async src="small.js" />
<!-- Bu satır script dosyasını beklemeden görünür hale gelecektir-->
<p id="second-p">Bu satır script etiketinden sonra</p>
</body>
Önceki örnekte defer
kullandığımız için dosya sırası korunurken, burada dosyalar asenkron şekilde indirilip çalıştırılmaya başlayacak ve small.js
boyutu küçük olduğu için muhtemelen daha önce çalışacaktır.
Özellikle 3.parti scriptlerin çoğunun dökümanında bu async
attribute zaten yer alır. Mesela Google Analytics sayfanın görünürlüğü ile bir ilgisi olmadığı için asenkron şekilde HTML ile birlikte arkada inecek ve performansı gereksiz yere yormayacaktır.
Sonuç olarak; her iki attribute için de asıl amaç script indirilirken sayfayı bloklamamaktır.
# | Sıralama | DOMContentLoaded |
---|---|---|
async | script sırası önemli olmadan ilk indirilen önce çalışır | HTML'in ya da scriptin boyutuna göre çalışma sırası ile ilgili bir kesin bir garantisi yoktur. Boyutu küçük olan önce çalışır. |
defer | script sırası bildirilen sıraya göre indirilerek çalıştırılır | HTML tamamen yüklenip parse edildikten sonra bu event öncesinde çalışır. |
Hangisini, Nerede, Ne Zaman Kullanalım?
Eee madem bu kadar avantajı var o zaman tüm scriptlere async
ya da defer
verelim gitsin... mi?🤔Bu tamamen projedeki önceliklerinize bağlı. Yani bu iki attribute kullanıldığı zaman scriptler indirip çalıştırılmadan sayfa kullanıcıya gösterilir; scriptler ile sayfada yapacağınız ayarlamalar henüz sayfada kullanılabilir durumda değildir. Bu durumda script indirilip çalıştırılana kadar sayfada görsel bozulmalar, kaymalar meydana gelecek, daha sonra toparlayacaktır.
Arama motorları, bir siteye geldiğinde bizim gözle gördüğümüz gibi yorumlamayacaktır. Yani daha sade bir dille; arama motoru dediğimiz milisaniyelik 'ziyaretçi' sadece koddan anlar ve aslında bizim gözümüze hoş gelen her animasyon onu koda odaklanmaktan alıkoyacağı için bundan pek hoşlanmaz. O yüzden en hızlı ve SEO dostu siteler kupkuru HTML çıktıları olan sitelerdir. Mesela ben, her ne kadar kupkuru bir HTML en iyisidir desem de bu sitede bir sürü animasyona izin verdim ancak temel script dosyam için bile bu argümanları kullandım çünkü performans tarafını öne çekmek istedim. Bu yüzden bazen sayfanın ilk açılışında toparlanmasını gözle fark edebilirsiniz. Bazen sitelerin yüklendiğini bildiren loading animasyonları bunu gizlemek için kullanılır. Bu yüzden şu yol doğrudur diye bir şey olmaz, ben sadece kullanımlarından bahsettim. Bunun kararını hız & erişilebilirlik & görsellik gibi ihtiyaçların kesişimine göre, proje özelinde kendiniz vermelisiniz.👍
cemil Aydoğdu
2 yıl önceMerhabalar uzun zamandır nesnelere yönelik algoritma programlama nasıl programlanır araştırdım durdum bu araştırma sonucunda bir çok şey öğrendim öğrenmesine ama programlamayı bir türlü çalıştıran adım değerli okurum ve uzman arkaşim bana video ile adım adım anlatır mısın anlatırsan sevinirim bir projedir kafamda kurkuladigim ve kurkuladigim bu proje bir çok kaynaklar nesleler üzerindeki algoritma analizi mümkün olduğu yazıyor lütfen yardım edebilir misiniz ihtiyacım var aç gözlü bir insan değilim çalışıyorum yettiremiyorum ev kira askeri ücret ile geçinmek oldukça zor yokluk ve yetersizlik his etmek bir erkeğin bir kadınına yetersiz kalmak boynumuzu eğmek bir erkek için cekilinmez bir hal alıyor nedir yazacağımız günler sayılı mutlu olmak hepimizin hakkı para ile mesut olunmaz ama parasız da sadet olmuyor işte beni anladiginizi umuyorum yardımlarinizi bekliyorum teşekkür ederim büyülerimin ellerinden küçüklerin gözlerinden öperim.
gürkan tuna
2 yıl önceMerhaba Cemil Bey, eğer olmuyorsa daha fazla zorlamayın bence; belli ki psikolojik olarak da sizi fazlasıyla yormuş. Şu an yaptığınız işe daha uygun🎯ek gelir getirecek başka bir uğraşa yönelmeniz çok daha yerinde olacaktır. Sevgiler
Biri
bir yıl önceGürkan bey bu yazınız ile karşınızdaki insanı belliki kırmışsınız ve sizi gerçekten kibirli gördüm bir video da olsa insanın hevesini kırmasaydınız iyidir. neyse allah hidayet versin size
özkan
bir yıl önceGayet net ve anlaşılır bir yazı olmuş. Elinize sağlık.