Web sayfasının yüklenmesi ve yürütme sırası?


244

Bazı web tabanlı projeler yaptım, ancak sıradan bir web sayfasının yükleme ve yürütme sırası hakkında çok fazla düşünmüyorum. Ama şimdi detayı bilmem gerekiyor. Google veya SO'dan yanıt bulmak zor, bu yüzden bu soruyu oluşturdum.

Örnek bir sayfa şöyle:

<html>
 <head>
  <script src="jquery.js" type="text/javascript"></script>
  <script src="abc.js" type="text/javascript">
  </script>
  <link rel="stylesheets" type="text/css" href="abc.css"></link>
  <style>h2{font-wight:bold;}</style>
  <script>
  $(document).ready(function(){
     $("#img").attr("src", "kkk.png");
  });
 </script>
 </head>
 <body>
    <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
    <script src="kkk.js" type="text/javascript"></script>
 </body>
</html>

Sorularım işte burada:

  1. Bu sayfa nasıl yükleniyor?
  2. Yüklemenin sırası nedir?
  3. JS kodu ne zaman yürütülür? (satır içi ve harici)
  4. CSS ne zaman yürütülür (uygulanır)?
  5. $ (Document) .ready ne zaman yürütülür?
  6. Abc.jpg indirilecek mi? Yoksa sadece kkk.png dosyasını mı indiriyor?

Aşağıdaki anlayışa sahibim:

  1. Tarayıcı ilk önce html'yi (DOM) yükler.
  2. Tarayıcı harici kaynakları yukarıdan aşağıya satır satır yüklemeye başlar.
  3. A <script>karşılanırsa, yükleme engellenir ve JS dosyası yüklenip yürütülene kadar bekleyin ve devam edin.
  4. Diğer kaynaklar (CSS / görüntüler) paralel olarak yüklenir ve gerekirse yürütülür (CSS gibi).

Yoksa böyle mi:

Tarayıcı html'yi (DOM) ayrıştırır ve harici kaynakları bir dizi veya yığın benzeri yapıda alır. Html yüklendikten sonra, tarayıcı tüm kaynakları yükleyene kadar harici kaynakları yapıya paralel olarak yüklemeye ve yürütmeye başlar. Daha sonra DOM, JS'ye bağlı olarak kullanıcının davranışlarına karşılık gelecek şekilde değiştirilecektir.

Bir HTML sayfasının yanıtını aldığınızda neler olduğu hakkında ayrıntılı bir açıklama yapan var mı? Bu, farklı tarayıcılarda farklılık gösterir mi? Bu soru hakkında referans var mı?

Teşekkürler.

DÜZENLE:

Firebug ile Firefox'ta bir deneme yaptım. Ve aşağıdaki görüntü olarak gösterir: alternatif metin


11
Steve Souders bu alanda çok çalışmıştır. Steve + souders + yüksek + performansı için Google ve bir göz atın.
anddoutoi

3
Performans ayarı demek istemiyorum. Detayı bilmek istiyorum.
Zhu Tao

2
Onun çalışmasını okuduğumda, "nasıl" detaylı çalıştığı konusundaki anlayışım on kat arttı, bu yüzden hala geçerli bir yorum. Telif hakkı tarafından kitabın tamamını burada alıntılamasına izin verilmiyor, bu yüzden hala onun çalışmasına bakmanızı öneririm.
anddoutoi


Yanıtlar:


277

Numunenize göre,

<html>
 <head>
  <script src="jquery.js" type="text/javascript"></script>
  <script src="abc.js" type="text/javascript">
  </script>
  <link rel="stylesheets" type="text/css" href="abc.css"></link>
  <style>h2{font-wight:bold;}</style>
  <script>
  $(document).ready(function(){
     $("#img").attr("src", "kkk.png");
  });
 </script>
 </head>
 <body>
    <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
    <script src="kkk.js" type="text/javascript"></script>
 </body>
</html>

kabaca yürütme akışı aşağıdaki gibidir:

  1. HTML belgesi indiriliyor
  2. HTML belgesinin ayrıştırılması başlar
  3. HTML Ayrıştırma ulaşır <script src="jquery.js" ...
  4. jquery.js indirilir ve ayrıştırılır
  5. HTML ayrıştırma ulaşır <script src="abc.js" ...
  6. abc.js indirilir, ayrıştırılır ve çalıştırılır
  7. HTML ayrıştırma ulaşır <link href="abc.css" ...
  8. abc.css indirilir ve ayrıştırılır
  9. HTML ayrıştırma ulaşır <style>...</style>
  10. Dahili CSS kuralları ayrıştırılır ve tanımlanır
  11. HTML ayrıştırma ulaşır <script>...</script>
  12. Dahili Javascript ayrıştırılır ve çalıştırılır
  13. HTML Ayrıştırma ulaşır <img src="abc.jpg" ...
  14. abc.jpg indirildi ve görüntülendi
  15. HTML Ayrıştırma ulaşır <script src="kkk.js" ...
  16. kkk.js indirilir, ayrıştırılır ve çalıştırılır
  17. HTML belgesi uçlarının ayrıştırılması

İndirme işleminin, tarayıcının davranışları nedeniyle eşzamansız ve engellemeyebileceğini unutmayın. Örneğin, Firefox'ta alan adı başına eşzamanlı istek sayısını sınırlayan bu ayar vardır.

Ayrıca, bileşenin önceden önbelleğe alınmış olup olmamasına bağlı olarak, bileşen yakın gelecekteki bir istekte yeniden istenmeyebilir. Bileşen önbelleğe alınmışsa, bileşen gerçek URL yerine önbellekten yüklenir.

Ayrıştırma sona erdiğinde ve belge hazır ve yüklendiğinde olaylar onloadtetiklenir. Böylece ne zaman onloadkovulur, $("#img").attr("src","kkk.png");koşulur. Yani:

  1. Doküman hazır, yüklendi.
  2. Javascript yürütme isabetleri $("#img").attr("src", "kkk.png");
  3. kkk.png indirilir ve yüklenir #img

$(document).ready()Olay aslında tüm sayfası bileşenleri yüklendi ve hazır olduğunda ateş olaydır. Bununla ilgili daha fazla bilgi edinin: http://docs.jquery.com/Tutorials:Introducing_$ (belge) .ready ()

Düzenle - Bu kısım, paralel veya daha fazla kısımda daha ayrıntılı olarak açıklanmaktadır:

Varsayılan olarak ve şu anki kavrama göre, tarayıcı genellikle her sayfayı 3 şekilde çalıştırır: HTML ayrıştırıcı, Javascript / DOM ve CSS.

HTML ayrıştırıcı, biçimlendirme dilini ayrıştırmak ve yorumlamaktan sorumludur ve bu nedenle diğer 2 bileşene çağrı yapabilmelidir.

Örneğin, ayrıştırıcı bu çizgiyle karşılaştığında:

<a href="#" onclick="alert('test');return false;" style="font-weight:bold">a hypertext link</a>

Ayrıştırıcı, ikisi Javascript ve biri CSS olmak üzere 3 çağrı yapacaktır. İlk olarak, ayrıştırıcı bu öğeyi oluşturur ve bu öğeyle ilgili tüm özniteliklerle birlikte DOM ad alanına kaydeder. İkinci olarak, ayrıştırıcı onclick olayını bu öğeye bağlamak için çağrıda bulunacaktır. Son olarak, bu belirli öğeye CSS stilini uygulamak için CSS iş parçacığını başka bir çağrı yapar.

Yürütme yukarıdan aşağıya ve tek iş parçacıklı. Javascript çok iş parçacıklı görünebilir, ancak gerçek şu ki Javascript tek iş parçacıklıdır. Bu nedenle harici javascript dosyası yüklenirken, ana HTML sayfasının ayrıştırılması askıya alınır.

Bununla birlikte, CSS dosyaları aynı anda indirilebilir çünkü CSS kuralları her zaman uygulanır - yani, elemanlar her zaman tanımlanan en taze CSS kuralları ile yeniden boyanır - böylece engellemeyi kaldırır.

Bir öğe yalnızca ayrıştırıldıktan sonra DOM'da kullanılabilir. Bu nedenle, belirli bir öğeyle çalışırken komut dosyası her zaman pencere onload olayının arkasına veya içine yerleştirilir.

Bunun gibi komut dosyaları hataya neden olur (jQuery'de):

<script type="text/javascript">/* <![CDATA[ */
  alert($("#mydiv").html());
/* ]]> */</script>
<div id="mydiv">Hello World</div>

Çünkü komut dosyası ayrıştırıldığında, #mydivöğe hala tanımlanmamıştır. Bunun yerine bu işe yarar:

<div id="mydiv">Hello World</div>
<script type="text/javascript">/* <![CDATA[ */
  alert($("#mydiv").html());
/* ]]> */</script>

VEYA

<script type="text/javascript">/* <![CDATA[ */
  $(window).ready(function(){
                    alert($("#mydiv").html());
                  });
/* ]]> */</script>
<div id="mydiv">Hello World</div>

4
Teşekkürler. Ancak , tarayıcının davranışları nedeniyle indirme işleminin eşzamansız ve engellemeyebileceğini belirttiniz , bu nedenle asyn'de ne tür bileşenler indirilebilir (örnek olarak FF'yi alın)? <script>diğer bileşenleri engelleyecek, değil mi? Her tarayıcı için spec hakkında herhangi bir referans var mı?
Zhu Tao

4
$ (document) .ready () DOM tamamlandığında tetiklenir, tüm sayfa bileşenleri yüklendiğinde değil
Pierre

2
@Pierre by page komponentleri DOM demekti.
mauris

3
sadece açıklığa kavuşturmak için ... normal window.onload # 17'den sonra olur ... peki jquery'nin $ (document) .ready () 'nin kodu ne kadar çalışır? # 12? ancak DOM'un kendisi 1 numaraya yüklendi değil mi?
armyofda12mnkeys

1
<body> sekmesinde, <img> ve <script> etiketi arasına < link href = "bootstrap.min.css" rel = "stylesheet" /> eklersek, bootsrap indirilene kadar img görüntülenmez ... bence adım [13], [14] değişikliğe ihtiyaç duyuyor ... birisi bu davranışı açıklayabilir mi?
Bhuvan

34

1) HTML indirildi.

2) HTML aşamalı olarak ayrıştırılır. Bir varlık talebine ulaşıldığında tarayıcı varlığı indirmeye çalışır. Çoğu HTTP sunucusu ve çoğu tarayıcı için varsayılan yapılandırma, yalnızca iki isteği paralel olarak işlemektir. IE, paralel olarak sınırsız sayıda varlığı indirecek şekilde yeniden yapılandırılabilir. Steve Souders, IE'de 100'den fazla isteği paralel olarak indirebildi. Bunun istisnası, komut dosyası isteklerinin IE'deki paralel varlık isteklerini engellemesidir. Bu nedenle, tüm JavaScript'i harici JavaScript dosyalarına koymanız ve isteği HTML'deki kapanış gövdesi etiketinden hemen önce koymanız önemle tavsiye edilir.

3) HTML ayrıştırıldığında DOM oluşturulur. CSS, DOM'un neredeyse tüm kullanıcı aracılarında oluşturulmasına paralel olarak oluşturulur. Sonuç olarak, tüm CSS kodlarının, belgenin <head> </head> bölümünde mümkün olduğu kadar yüksek talep edilen harici CSS dosyalarına yerleştirilmesi önemle tavsiye edilir. Aksi takdirde sayfa DOM'da CSS istek konumunun oluşmasına kadar oluşturulur ve ardından oluşturma işlemi baştan başlar.

4) Yalnızca DOM tamamen oluşturulduktan ve sayfadaki tüm öğeler için istekler çözüldükten veya JavaScript zaman aşımı etkinliğinden zaman aşımına uğrarsa. IE7 ve IE8 hakkında emin değilim, varlık isteğinden bir HTTP yanıtı alınmazsa varlıkları hızlı bir şekilde zaman aşımına uğratmaz. Bu, sayfada JavaScript tarafından istenen bir öğenin, yani bir işlevde bulunmayan HTML etiketlerine yazılan JavaScript'in, onload etkinliğinin saatlerce yürütülmesini engelleyebileceği anlamına gelir. Sayfada böyle bir satır içi kod varsa ve bir kod çökmesine neden olan bir ad alanı çakışması nedeniyle yürütülemiyorsa, bu sorun tetiklenebilir.

Yukarıdaki adımlardan en fazla CPU yoğun olanı DOM / CSS'nin ayrıştırılmasıdır. Sayfanızın daha hızlı işlenmesini istiyorsanız, yinelenen talimatları ortadan kaldırarak ve CSS talimatlarını mümkün olan en az öğe referansına birleştirerek verimli CSS yazın. DOM ağacınızdaki düğüm sayısını azaltmak da daha hızlı görüntü oluşturma sağlar.

HTML'nizden veya CSS / JavaScript öğelerinizden istediğiniz her bir öğenin ayrı bir HTTP üstbilgisi ile talep edildiğini unutmayın. Bu bant genişliği tüketir ve istek başına işlem gerektirir. Sayfanızın olabildiğince hızlı yüklenmesini istiyorsanız, HTTP isteklerinin sayısını ve HTML'nizin boyutunu azaltın. Kullanıcı ağırlığınızı yalnızca HTML'den 180 bin sayfa ağırlığına sahip olarak herhangi bir iyilik yapmıyorsunuz. Birçok geliştirici, bir kullanıcının 6 nanosaniyede sayfadaki içeriğin kalitesi hakkında fikrini oluşturduğuna ve ardından DNS sorgusunu sunucusundan temizlediğine ve hoşnut değilse bilgisayarını yaktığına dair bir yanlışlığa abone olur, bunun yerine mümkün olan en güzel sayfayı sağlarlar. 250 bin HTML. Bir kullanıcının sayfalarınızı daha hızlı yükleyebilmesi için HTML'nizi kısa ve tatlı tutun.


2
CSS talimatlarını mümkün olan en az eleman referansına birleştirmek Kulağa tuhaf geliyor. Üç öğeye stil vermem gerekirse tam olarak üç öğeye başvurmam gerekir. Biri on stile başvuramıyorum, değil mi? Veya bunun üzerinde
Green

12

Sayfanızı Firefox'ta açın ve HTTPFox eklentisini edinin. Size ihtiyacınız olan her şeyi söyleyecektir.

Bunu archivist.incuito'da buldum:

http://archivist.incutio.com/viewlist/css-discuss/76444

Bir sayfayı ilk kez talep ettiğinizde, tarayıcınız sunucuya bir GET isteği gönderir, bu da HTML'yi tarayıcıya döndürür. Tarayıcı daha sonra sayfayı ayrıştırmaya başlar (büyük olasılıkla sayfanın tamamı döndürülmeden önce).

Bir CSS dosyası, bir görüntü dosyası, bir komut dosyası, bir Flash dosyası veya sayfanın dışındaki herhangi bir şeye (aynı sunucuda / etki alanında olsun ya da olmasın) gibi harici bir varlığa referans bulduğunda, bu kaynak için başka bir GET isteği.

Ancak HTTP standardı, tarayıcının aynı etki alanına ikiden fazla eşzamanlı istekte bulunmaması gerektiğini belirtir. Bu nedenle, her isteği bir kuyruktaki belirli bir etki alanına koyar ve her varlık döndürüldüğünde, o etki alanının kuyruğunda bir sonraki isteği başlatır.

Bir varlığın geri gönderilmesi için gereken süre, boyutuna, sunucunun şu anda yaşadığı yüke ve tarayıcıyı çalıştıran makine ile sunucu arasındaki her bir makinenin etkinliğine bağlıdır. Bu makinelerin listesi prensip olarak her bir talep için farklı olabilir; daha uzun sürer. Böylece, bir sayfanın üç komut dosyasına ve farklı görüntü boyutlarına sahip beş görüntü dosyasına (bu sırayla) başvurduğu aşağıdaki gibi bir sıra elde edebilirsiniz:

  1. Script1 ve script2'yi alın; script3 ve images1-5 için kuyruk isteği.
  2. script2 geliyor (script1'den daha küçüktür): script3, kuyruk images1-5.
  3. script1 gelir; GET image1, kuyruk görüntüleri2-5.
  4. image1 geldiğinde, image2'yi al, kuyruk görüntüleri3-5.
  5. script3 bir ağ sorunu nedeniyle gelemiyor - script3'ü tekrar GET (otomatik yeniden deneme).
  6. image2 geldi, script3 hala burada değil; Resim3, kuyruk resimleri4-5 alın.
  7. resim 3 geldi; İmage4, kuyruk image5, script3 hala yolda.
  8. image4 geldi, GET image5;
  9. image5 geldi.
  10. script3 geldi.

Kısacası: Sunucunun ne yaptığına, İnternet'in geri kalanının ne yaptığına ve herhangi bir şeyin hata içerip içermediğine ve yeniden getirilmesi gerekip gerekmediğine bağlı olarak herhangi bir eski sipariş. Bu, işleri yapmak için garip bir yol gibi görünebilir, ancak internetin (sadece WWW değil) bu şekilde yapılmazsa herhangi bir güvenilirlik derecesi ile çalışması tam anlamıyla imkansız olacaktır.

Ayrıca, tarayıcının dahili kuyruğu varlıkları sayfada göründükleri sırayla getirmeyebilir - herhangi bir standart için zorunlu değildir.

(Oh, ve hem tarayıcıda hem de ISP'ler tarafından ağdaki yükü hafifletmek için kullanılan önbellek proxy'lerinde önbelleğe almayı unutmayın.)



2

AFAIK, tarayıcı (en azından Firefox) her kaynağı ayrıştırır ayrılmaz talep eder. Bir img etiketi ile karşılaşırsa, img etiketi ayrıştırılır ayrılmaz bu görüntüyü talep edecektir. Ve bu, HTML belgesinin toplamını almadan önce bile olabilir ... yani bu gerçekleştiğinde hala HTML belgesini indiriyor olabilir.

Firefox için, nasıl ayarlandıklarına bağlı olarak geçerli olan tarayıcı kuyrukları vardır: config. Örneğin, aynı sunucudan aynı anda 8'den fazla dosya indirmeye çalışmaz ... ek istekler sıraya alınır. Mozilla web sitesinde belgelenen ve about: config'de ayarlanabilen etki alanı başına sınırlar, proxy başına sınırlamalar ve diğer şeyler olduğunu düşünüyorum. IE'de böyle bir sınırın olmadığı bir yerde okudum.

Ana HTML belgesi indirilip DOM ayrıştırılır ayrılmaz jQuery ready olayı başlatılır . Ardından, bağlı tüm kaynaklar (CSS, resimler vb.) İndirilip ayrıştırıldıktan sonra load olayı tetiklenir. JQuery belgelerinde açıkça belirtilmiştir.

Tüm bunların yüklendiği sırayı kontrol etmek istiyorsanız, bunu yapmanın en güvenilir yolunun JavaScript aracılığıyla olduğuna inanıyorum.



1

Seçilen cevap en azından Firefox 52'de modern tarayıcılar için geçerli değil gibi gözüküyor

<html>
  <head>
    <!-- prints the date before parsing and blocks HTMP parsering -->
    <script>
      console.log("start: " + (new Date()).toISOString());
      for(var i=0; i<1000000000; i++) {};
    </script>

    <script src="jquery.js" type="text/javascript"></script>
    <script src="abc.js" type="text/javascript"></script>
    <link rel="stylesheets" type="text/css" href="abc.css"></link>
    <style>h2{font-wight:bold;}</style>
    <script>
      $(document).ready(function(){
      $("#img").attr("src", "kkk.png");
     });
   </script>
 </head>
 <body>
   <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
   <script src="kkk.js" type="text/javascript"></script>
   </body>
</html>

Ne css ve javascript kaynakları yüklemek için isteklerin başlangıç ​​zamanı engellenmediğini buldum. Görünüşe göre Firefox'un bir HTML taraması var ve HTML'yi ayrıştırmaya başlamadan önce temel kaynakları (img kaynağı dahil değil) tanımlayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.