Memuat dan urutan eksekusi halaman web?

244

Saya telah melakukan beberapa proyek berbasis web, tetapi saya tidak terlalu memikirkan beban dan urutan eksekusi dari halaman web biasa. Tapi sekarang saya perlu tahu detailnya. Sulit untuk menemukan jawaban dari Google atau SO, jadi saya membuat pertanyaan ini.

Halaman contohnya seperti ini:

<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>

Jadi inilah pertanyaanku:

  1. Bagaimana cara memuat halaman ini?
  2. Apa urutan pemuatannya?
  3. Kapan kode JS dieksekusi? (inline dan eksternal)
  4. Kapan CSS dieksekusi (diterapkan)?
  5. Kapan $ (dokumen). Sudah dieksekusi?
  6. Akankah abc.jpg diunduh? Atau apakah itu hanya mengunduh kkk.png?

Saya memiliki pemahaman sebagai berikut:

  1. Browser memuat html (DOM) pada awalnya.
  2. Browser mulai memuat sumber daya eksternal dari atas ke bawah, baris demi baris.
  3. Jika a <script>terpenuhi, pemuatan akan diblokir dan menunggu sampai file JS dimuat dan dieksekusi dan kemudian melanjutkan.
  4. Sumber daya lain (CSS / gambar) dimuat secara paralel dan dieksekusi jika diperlukan (seperti CSS).

Atau seperti ini:

Browser mem-parsing html (DOM) dan mendapatkan sumber daya eksternal dalam susunan atau susunan seperti susunan. Setelah html dimuat, browser mulai memuat sumber daya eksternal dalam struktur secara paralel dan mengeksekusi, sampai semua sumber daya dimuat. Maka DOM akan diubah sesuai dengan perilaku pengguna tergantung pada JS.

Adakah yang bisa memberikan penjelasan terperinci tentang apa yang terjadi ketika Anda mendapat respons dari halaman html? Apakah ini bervariasi di berbagai browser? Adakah referensi tentang pertanyaan ini?

Terima kasih.

EDIT:

Saya melakukan percobaan di Firefox dengan Firebug. Dan itu ditampilkan sebagai gambar berikut: teks alternatif

Zhu Tao
sumber
11
Steve Souders telah melakukan banyak pekerjaan di bidang ini. Google untuk steve + souders + kinerja + tinggi dan lihatlah.
anddoutoi
3
Maksud saya bukan penyempurnaan kinerja. Saya ingin tahu detailnya.
Zhu Tao
2
Dengan membaca karyanya, pemahaman saya tentang bagaimana "itu" bekerja secara detail meningkat sepuluh kali lipat sehingga masih merupakan komentar yang valid. Saya tidak diizinkan oleh hak cipta untuk mengutip seluruh bukunya di sini, jadi saya tetap menyarankan Anda mencari pekerjaannya.
anddoutoi
3
Deskripsi hebat tentang urutan sesuatu terjadi ada di sini
Gerrat

Jawaban:

277

Menurut sampel anda,

<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>

kira-kira alur eksekusi adalah sebagai berikut:

  1. Dokumen HTML diunduh
  2. Penguraian dokumen HTML dimulai
  3. Parsing HTML mencapai <script src="jquery.js" ...
  4. jquery.js diunduh dan diuraikan
  5. Penguraian HTML mencapai <script src="abc.js" ...
  6. abc.js diunduh, diuraikan dan dijalankan
  7. Penguraian HTML mencapai <link href="abc.css" ...
  8. abc.css diunduh dan diuraikan
  9. Penguraian HTML mencapai <style>...</style>
  10. Aturan CSS internal diuraikan dan didefinisikan
  11. Penguraian HTML mencapai <script>...</script>
  12. Javascript internal diuraikan dan dijalankan
  13. Parsing HTML mencapai <img src="abc.jpg" ...
  14. abc.jpg diunduh dan ditampilkan
  15. Parsing HTML mencapai <script src="kkk.js" ...
  16. kkk.js diunduh, diuraikan dan dijalankan
  17. Parsing dokumen HTML berakhir

Perhatikan bahwa unduhan mungkin tidak sinkron dan non-pemblokiran karena perilaku peramban. Misalnya, di Firefox ada pengaturan ini yang membatasi jumlah permintaan simultan per domain.

Juga tergantung pada apakah komponen telah di-cache atau tidak, komponen mungkin tidak diminta lagi dalam permintaan waktu dekat. Jika komponen telah di-cache, komponen akan dimuat dari cache alih-alih URL yang sebenarnya.

Ketika parsing berakhir dan dokumen siap dan dimuat, acara onloaddipecat. Jadi ketika onloaddipecat, $("#img").attr("src","kkk.png");dijalankan. Begitu:

  1. Dokumen siap, onload dipecat.
  2. Eksekusi eksekusi Javascript $("#img").attr("src", "kkk.png");
  3. kkk.png diunduh dan dimuat ke #img

The $(document).ready()event sebenarnya acara dipecat ketika semua komponen halaman dimuat dan siap. Baca lebih lanjut tentang hal ini: http://docs.jquery.com/Tutorials:Introducing_$ (document) .ready ()

Sunting - Bagian ini menguraikan lebih banyak pada bagian paralel atau tidak:

Secara default, dan dari pemahaman saya saat ini, browser biasanya menjalankan setiap halaman dengan 3 cara: HTML parser, Javascript / DOM, dan CSS.

Pengurai HTML bertanggung jawab untuk mem-parsing dan menafsirkan bahasa markup dan dengan demikian harus dapat membuat panggilan ke 2 komponen lainnya.

Misalnya ketika parser melewati garis ini:

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

Parser akan membuat 3 panggilan, dua ke Javascript dan satu ke CSS. Pertama, parser akan membuat elemen ini dan mendaftarkannya di ruang nama DOM, bersama dengan semua atribut yang terkait dengan elemen ini. Kedua, pengurai akan memanggil untuk mengikat acara onclick ke elemen khusus ini. Terakhir, itu akan membuat panggilan lain ke utas CSS untuk menerapkan gaya CSS ke elemen khusus ini.

Eksekusi top down dan single threaded Javascript mungkin terlihat multi-utas, tetapi faktanya Javascript adalah utas tunggal. Inilah sebabnya mengapa ketika memuat file javascript eksternal, penguraian halaman HTML utama ditangguhkan.

Namun, file CSS dapat diunduh secara bersamaan karena aturan CSS selalu diterapkan - artinya elemen mengatakan selalu dicat ulang dengan aturan CSS paling segar yang ditentukan - sehingga membuatnya tidak terhapus.

Sebuah elemen hanya akan tersedia di DOM setelah diurai. Dengan demikian ketika bekerja dengan elemen tertentu, skrip selalu ditempatkan setelah, atau dalam acara jendela yang memuat.

Script seperti ini akan menyebabkan kesalahan (pada jQuery):

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

Karena ketika skrip diuraikan, #mydivelemen masih belum didefinisikan. Sebaliknya ini akan berhasil:

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

ATAU

<script type="text/javascript">/* <![CDATA[ */
  $(window).ready(function(){
                    alert($("#mydiv").html());
                  });
/* ]]> */</script>
<div id="mydiv">Hello World</div>
mauris
sumber
4
Terima kasih. Tapi Anda menyebutkan unduhan mungkin asinkron dan non-pemblokiran karena perilaku peramban , jadi komponen apa yang dapat diunduh di asyn (ambil FF sebagai contoh)? <script>akan memblokir komponen lain, bukan? Adakah referensi tentang spesifikasi untuk setiap browser?
Zhu Tao
4
$ (dokumen) .ready () dipecat ketika DOM selesai, bukan ketika semua komponen halaman dimuat
Pierre
2
@ Perbatasan dengan komponen halaman yang saya maksud DOM -> komponen apa pun di DOM.
mauris
3
hanya untuk memperjelas ... window.onload biasa terjadi setelah # 17 ... jadi pada # apa jquery $ (dokumen). Sudah () menjalankan kode? # 12? tetapi DOM itu sendiri dimuat di # 1 kan?
armyofda12mnkeys
1
Jika di tab <body>, jika kita menambahkan <link href = "bootstrap.min.css" rel = "stylesheet" /> antara tag <img> dan <script> daripada img tidak ditampilkan hingga imbrak bootrap diunduh ... jadi saya pikir langkah [13], [14] perlu modifikasi ... dapatkah seseorang menjelaskan perilaku itu?
Bhuvan
34

1) HTML diunduh.

2) HTML diuraikan secara progresif. Ketika permintaan aset tercapai, browser akan mencoba mengunduh aset. Konfigurasi default untuk sebagian besar server HTTP dan sebagian besar browser adalah untuk memproses hanya dua permintaan secara paralel. IE dapat dikonfigurasi ulang untuk mengunduh aset dalam jumlah tak terbatas secara paralel. Steve Souders telah dapat mengunduh lebih dari 100 permintaan secara paralel di IE. Pengecualian adalah bahwa permintaan skrip memblokir permintaan aset paralel di IE. Inilah sebabnya mengapa sangat disarankan untuk meletakkan semua JavaScript dalam file JavaScript eksternal dan meletakkan permintaan sesaat sebelum tag penutup tubuh dalam HTML.

3) Setelah HTML diuraikan, DOM diberikan. CSS diberikan bersamaan dengan rendering DOM di hampir semua agen pengguna. Karenanya sangat disarankan untuk meletakkan semua kode CSS ke file CSS eksternal yang diminta setinggi mungkin di bagian <head> </head> dokumen. Kalau tidak, halaman diberikan hingga terjadinya posisi permintaan CSS di DOM dan kemudian rendering dimulai dari atas.

4) Hanya setelah DOM benar-benar diberikan dan permintaan untuk semua aset di halaman tersebut diselesaikan atau waktu habis apakah JavaScript mengeksekusi dari peristiwa onload. IE7, dan saya tidak yakin tentang IE8, tidak cepat habis aset jika respon HTTP tidak diterima dari permintaan aset. Ini berarti aset yang diminta oleh JavaScript sebaris ke halaman, yaitu JavaScript yang ditulis ke dalam tag HTML yang tidak terkandung dalam suatu fungsi, dapat mencegah pelaksanaan peristiwa yang dimuat selama berjam-jam. Masalah ini dapat dipicu jika kode inline tersebut ada di halaman dan gagal dieksekusi karena tabrakan namespace yang menyebabkan crash kode.

Dari langkah-langkah di atas, salah satu yang paling intensif CPU adalah penguraian DOM / CSS. Jika Anda ingin halaman Anda diproses lebih cepat maka tuliskan CSS yang efisien dengan menghilangkan instruksi yang berlebihan dan mengkonsolidasikan instruksi CSS ke dalam referensi elemen sesedikit mungkin. Mengurangi jumlah node di pohon DOM Anda juga akan menghasilkan rendering lebih cepat.

Ingatlah bahwa setiap aset yang Anda minta dari HTML atau bahkan dari aset CSS / JavaScript Anda diminta dengan tajuk HTTP terpisah. Ini menghabiskan bandwidth dan membutuhkan pemrosesan per permintaan. Jika Anda ingin memuat halaman Anda secepat mungkin, kurangi jumlah permintaan HTTP dan kurangi ukuran HTML Anda. Anda tidak melakukan bantuan pengguna Anda dengan rata-rata berat halaman 180k dari HTML saja. Banyak pengembang berlangganan kekeliruan bahwa pengguna mengambil keputusan tentang kualitas konten pada halaman dalam 6 nanodetik dan kemudian membersihkan kueri DNS dari servernya dan membakar komputernya jika tidak senang, jadi alih-alih mereka memberikan halaman yang paling indah di 250k HTML. Buat HTML Anda pendek dan manis sehingga pengguna dapat memuat halaman Anda lebih cepat.


sumber
2
mengkonsolidasikan instruksi CSS ke dalam referensi elemen sesedikit mungkin Kedengarannya aneh. Jika saya perlu menata tiga elemen, saya perlu merujuk tepat tiga elemen. Saya tidak bisa merujuk satu ke gaya sepuluh, bukan? Atau uraikan hal itu
Green
12

Buka halaman Anda di Firefox dan dapatkan addon HTTPFox. Ini akan memberi tahu Anda semua yang Anda butuhkan.

Menemukan ini di archivist.incuito:

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

Saat Anda pertama kali meminta halaman, browser Anda mengirimkan permintaan GET ke server, yang mengembalikan HTML ke browser. Browser kemudian mulai menguraikan halaman (mungkin sebelum semuanya telah dikembalikan).

Ketika menemukan referensi ke entitas eksternal seperti file CSS, file gambar, file skrip, file Flash, atau apa pun yang eksternal ke halaman (baik di server / domain yang sama atau tidak), ia bersiap untuk membuat permintaan GET lebih lanjut untuk sumber daya itu.

Namun standar HTTP menetapkan bahwa browser tidak boleh membuat lebih dari dua permintaan bersamaan ke domain yang sama. Jadi itu menempatkan setiap permintaan ke domain tertentu dalam antrian, dan ketika setiap entitas dikembalikan itu mulai yang berikutnya dalam antrian untuk domain itu.

Waktu yang diperlukan untuk mengembalikan suatu entitas tergantung pada ukurannya, beban yang dialami server saat ini, dan aktivitas setiap mesin tunggal antara mesin yang menjalankan browser dan server. Daftar mesin-mesin ini pada prinsipnya bisa berbeda untuk setiap permintaan, sejauh satu gambar dapat melakukan perjalanan dari Amerika Serikat ke saya di Inggris melalui Atlantik, sementara yang lain dari server yang sama keluar melalui Pasifik, Asia dan Eropa, yang membutuhkan waktu lebih lama. Jadi, Anda mungkin mendapatkan urutan seperti berikut, di mana halaman memiliki (dalam urutan ini) referensi ke tiga file skrip, dan lima file gambar, semua ukuran yang berbeda:

  1. DAPATKAN script1 dan script2; permintaan antrian untuk script3 dan images1-5.
  2. script2 tiba (lebih kecil dari script1): DAPATKAN script3, antrian images1-5.
  3. script1 tiba; DAPATKAN image1, antrian gambar2-5.
  4. image1 tiba, DAPATKAN gambar2, antrian gambar3-5.
  5. script3 gagal tiba karena masalah jaringan - GET script3 lagi (coba lagi otomatis).
  6. image2 tiba, script3 masih belum ada di sini; DAPATKAN gambar3, gambar antrian4-5.
  7. gambar 3 tiba; DAPATKAN image4, antrian image5, script3 masih dalam perjalanan.
  8. image4 tiba, DAPATKAN image5;
  9. image5 tiba.
  10. script3 tiba.

Singkatnya: setiap pesanan lama, tergantung pada apa yang dilakukan server, apa yang dilakukan Internet, dan apakah ada sesuatu yang memiliki kesalahan dan harus diambil kembali. Ini mungkin tampak seperti cara aneh dalam melakukan sesuatu, tetapi secara harfiah mustahil bagi Internet (bukan hanya WWW) untuk bekerja dengan tingkat keandalan apa pun jika tidak dilakukan dengan cara ini.

Selain itu, antrian internal browser mungkin tidak mengambil entitas sesuai urutan yang ditampilkan di halaman - tidak diperlukan oleh standar apa pun.

(Oh, dan jangan lupa caching, baik di browser dan di caching proxy yang digunakan oleh ISP untuk meringankan beban di jaringan.)

tahdhaze09
sumber
6

Jika Anda menanyakan hal ini karena Anda ingin mempercepat situs web Anda, periksa halaman Yahoo tentang Praktik Terbaik untuk Mempercepat Situs Web Anda . Ini memiliki banyak praktik terbaik untuk mempercepat situs web Anda.

kutu buku yang dibayar
sumber
2

AFAIK, browser (setidaknya Firefox) meminta setiap sumber daya segera setelah diuraikan. Jika menemukan tag img, ia akan meminta gambar itu segera setelah tag img diuraikan. Dan itu bisa jadi bahkan sebelum ia menerima totalitas dokumen HTML ... itu masih bisa mengunduh dokumen HTML ketika itu terjadi.

Untuk Firefox, ada antrean peramban yang berlaku, tergantung bagaimana pengaturannya di: config. Misalnya tidak akan mencoba mengunduh lebih dari 8 file sekaligus dari server yang sama ... permintaan tambahan akan diantrekan. Saya pikir ada batas per-domain, per batas proxy, dan hal-hal lain, yang didokumentasikan di situs web Mozilla dan dapat diatur di about: config. Saya membaca di suatu tempat bahwa IE tidak memiliki batasan seperti itu.

Acara siap jQuery dipecat segera setelah dokumen HTML utama diunduh dan DOM diuraikan. Kemudian acara pemuatan diaktifkan setelah semua sumber daya tertaut (CSS, gambar, dll.) Telah diunduh dan diuraikan juga. Itu dibuat jelas dalam dokumentasi jQuery.

Jika Anda ingin mengontrol urutan semua yang dimuat, saya percaya cara yang paling dapat diandalkan untuk melakukannya adalah melalui JavaScript.

Rolf
sumber
1

Dynatrace AJAX Edition menunjukkan kepada Anda urutan pemuatan, parsing, dan eksekusi halaman yang tepat.

Chetan S
sumber
1

Jawaban yang dipilih sepertinya tidak berlaku untuk browser modern, setidaknya di Firefox 52. Yang saya amati adalah bahwa permintaan memuat sumber daya seperti css, javascript dikeluarkan sebelum parser HTML mencapai elemen, misalnya

<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>

Apa yang saya temukan bahwa waktu mulai permintaan untuk memuat sumber daya css dan javascript tidak diblokir. Sepertinya Firefox memiliki pemindaian HTML, dan mengidentifikasi sumber daya utama (sumber daya img tidak termasuk) sebelum mulai mem-parsing HTML.

Xiaoming
sumber