Modern websitelerinde, genellikle scriptler HTMLden daha baskndr: scriptlerin dosya/indirme boyutlar byktr ve ilenme sreleri uzundur.
Tarayc, HTMLi yklerken <script>...</script> etiketiyle karlatnda, DOMu oluturmaya devam edemez. Byle bir durumda scripti altrmak zorundadr. Benzer durum <script src="..."></script> eklinde dardan aktarlan scriptler iinde geerlidir: Tarayc script indirilene kadar bekleyecek, sonrasnda onu altracak ve en sonunda sayfann geri kalanan ileyecektir.
Bu durum iki nemli soruna yol aar:
- Scriptler, onlarn altndaki DOM elerini (element) gremeyebilir, yani ileyici fonksiyonlar (handlers) vb. ekleyemezsiniz.
- Sayfann st ksmnda byk bir script varsa, bu sayfann yklenmesini engeller. Kullanclar, script indirilip, altrlana kadar sayfa ieriini gremez.
<p>...script'ten nceki ierik...</p>
<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
<!-- Bu, script yklenene kadar gzkmeyecek -->
<p>...script'ten sonraki ierik...</p>
Bunun ii baz geici zmler vardr. rnein, scripti sayfann alt ksmna yerletirebiliriz. Bu sayede script, kendinden nce bulunan eleri grebilir ve sayfa ieriinin grntlenmesini engellemez:
<body>
...tm ierik script'in zerindedir...
<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
</body>
Fakat bu zm mkemmel olmaktan uzaktr. rnein, tarayc, scripti HTML belgesinin tamamn indirdikten sonra farkeder (ve onu indirmeye balayabilir). Uzun HTML belgelesi iin, bu fark edilebilir bir gecikme olabilir.
Bu tr durumlar ok hzl bir internet balantsna sahip olanlar iin nemsizdir, fakat dnyada birok insan hala yava bir internet hzna sahip ve mkemmel olmaktan uzak olan mobil interneti kullanyor.
Neyse ki, bizim iin bu sorunu zen iki tane <script> nitelii (attribute) vardr: defer ve async.
defer
defer nitelii, taraycya sayfay yklemeye devam etmesini, ve scriptin arkaplanda yklemesini, sonrasnda sayfa yklendikten sonra scriptin altrlmasn syler.
Yukardaki ile ayn rnek, fakat burada defer nitelii mevcut:
<p>...script'lerden nceki ierik...</p>
<script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
<!-- hemen grlebilir -->
<p>...script'lerden sonraki ierik...</p>
deferkullanlan script, sayfay engellemez.deferkullanlan script, her zaman DOM hazr olduunda,DOMContentLoadedolayndan (event) nce altrlr.
Aadaki rnek bunu gstermektedir:
<p>...script'lerden nceki ierik...</p>
<script>
document.addEventListener('DOMContentLoaded', () => alert("DOM ertelemeden (defer) sonra hazr!")); // (2)
</script>
<script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
<p>...script'lerden sonraki ierik...</p>
- Sayfa ierii hemen grnr.
DOMContentLoaded, ertelenmi (deferred) scripti bekler. Sadece script(2)indirilip, altrldnda tetiklenir.
Ertelenmi scriptler (deferred scripts), tpk normal scriptler gibi greli sralarn korurlar.
Yani, ilk olarak byk bir scripte ve sonrasnda kk bir tanesine sahipsek, sonuncusu bekler.
<script defer src="https://javascript.info/article/script-async-defer/long.js"></script>
<script defer src="https://javascript.info/article/script-async-defer/small.js"></script>
Tarayclar, performans artrmak iin sayfadaki komut dosyalarn tarar ve paralel/e zamanl olarak indirmeye balar. Yani yukardaki rnekte her iki komut dosyasda e zamanl olarak indirilir. Muhtemelen small.js ilk nce indirilecektir.
Ancak komut dosyalarnn sayfadaki sraya gre altrlmas gerekir, bu nedenle long.js altrlmasn bekler.
defer nitelii yalnzca dardan aktarlan komut dosyalar iindirEer <script> etiketinde src yoksa defer nitelii yok saylr.
async
async nitelii, bir scriptin tamamiyle bamsz olduu anlamna gelir:
- Sayfa asenkron scriptleri (async scripts) beklemez, ierik ilenir ve grntlenir.
DOMContentLoadedve asenkron scriptler (async scripts) birbirlerini beklemezler:DOMContentLoadedya bir asenkron scriptten (async script) nce gerekleebilir (bir asenkron script sayfa tamamlandktan sonra yklemeyi bitirirse)- ya da bir asenkron scriptten sonra (bir asenkron script kk ya da HTTP nbelleinde mevcut ise)
- Dier scriptler,
asyncscriptleri iin,asyncscriptleri de onlar iin beklemez.
Dolasyla, birden fazla async scriptimiz varsa, onlar herhangi bir srada altrlr. lk nce hangisi yklenirse o altrlr:
<p>...script'lerden nceki ierik...</p>
<script>
document.addEventListener('DOMContentLoaded', () => alert("DOM hazr!"));
</script>
<script async src="https://javascript.info/article/script-async-defer/long.js"></script>
<script async src="https://javascript.info/article/script-async-defer/small.js"></script>
<p>...script'lerden sonraki ierik...</p>
- Sayfa ierii hemen grnr:
asyncsayfay engellemez. DOMContentLoaded,asyncden ncede gerekleebilir, sonrada gerekleebilir. Burada garanti yok.- Asenkron scriptler birbirlerini beklemezler. Kk script
small.jsikinci sradadr, fakat muhtemelenlong.jsden nce yklenecektir, dolaysyla nce o altrlacaktr. Buna ilk sradakini ykle denir.
Asenkron scriptler, bamsz bir nc taraf scripti sayfaya eklediimizde harikadr: sayalar, reklamlar vb. bizim scriptlerimize bal olmadklar iin komut dosyalarmz onlar beklememelidir.
<!-- Google Analytics genellikle bu ekilde eklenir -->
<script async src="https://google-analytics.com/analytics.js"></script>
Dinamik Komut Dosyalar (Dynamic Scripts)
Ayrca, JavaScript kullanarak dinamik olarak bir script ekleyebiliriz:
let script = document.createElement('script');
script.src = "/article/script-async-defer/long.js";
document.body.append(script); // (*)
Script (*), belgeye eklenir eklenmez yklenmeye balar.
Dinamik scriptler varsaylan olarak async gibi davranr
Yani:
- Onlar herhangi bir eyi beklemezler, hibir eyde onlar beklemez.
- lk yklenen script, nce altrlr (ilk sradakini ykle)
async zelliini false olarak ayarlarsak, ykleme srasn belge sras olacak ekilde deitirebiliriz:
let script = document.createElement('script');
script.src = "/article/script-async-defer/long.js";
script.async = false;
document.body.append(script);
rnein, burada iki adet script ekledik. script.async=false olmadndan ilk sradakini ykleye gre altrlacakt (muhtemelen small.js nce alacakt). Fakat bu flag sayesinde sra belgedeki sra gibi olur.
function loadScript(src) {
let script = document.createElement('script');
script.src = src;
script.async = false;
document.body.append(script);
}
// long.js, async=false olduundan dolay nce altrlr.
loadScript("/article/script-async-defer/long.js");
loadScript("/article/script-async-defer/small.js");
zet
async ve defer niteliklerinin ortak bir zellii vardr: sayfann yklenmesini (render) engellemezler. Bylece kullanc sayfa ieriini okuyabilir ve sayfayla hemen etkileime geebilir.
Ancak aralarnda temel farkllklar vardr:
| Sra | DOMContentLoaded |
|
|---|---|---|
async |
lk sray ykle. Belgedeki sralar nemleri deildir hangisi nce yklenirse | Alakasz. Henz belgenin tamam indirilmemiken yklenebilir ve altrlabilir. Bu durum, eer scriptler kk veya nbellekte mevcut ise ve belge yeterince uzun ise gerekleir. |
defer |
Belge sras (belgeye girdikleri gibi). | Belge yklenip, zmlendendikten sonra (gerekirse beklerler), DOMContentLoaded olayndan (event) hemen nce altrlr. |
defer kullanyorsanz, ltfen sayfann script yklenmeden nce grntleneceini unutmayn.
Yani kullanclar sayfay okuyabilir, fakat baz grafiksel bileenler muhtemelen henz hazr deildir.
Kullancya neyin hazr olup, neyin olmadn gstermek iin uygun yerlere ykleniyor ifadesi yerletirilmeli, almayan dmeler (button) devre d braklmaldr.
Pratikte, defer tm DOMa ihtiya duyan ve/ya da greli yrtme sras nemli olan scriptler iin kullanlr. Ve async sayalar, reklamlar gibi bamsz scriptler iin kullanlr. Ve onlarda sra nemli deildir.
Yorumlar
<code>kullannz, birka satr eklemek iin ise<pre>kullann. Eer 10 satrdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)