Kata pengantar
Saya percaya semua orang telah menemukan banyak masalah mengenai pemuatan skrip JavaScript. Terutama di beberapa poin -
1> Masalah dengan pemuatan file, ketergantungan file dan urutan eksekusi yang disebabkan oleh skrip sinkron dan skrip asinkron
2> masalah optimasi kinerja yang disebabkan oleh skrip sinkron dan skrip asinkron
Pemahaman yang mendalam tentang semua aspek pemuatan skrip tidak hanya kondusif untuk memecahkan masalah praktis, tetapi juga kondusif untuk memahami dan melaksanakan optimasi kinerja.
Pertama -tama lihat kode tag skrip apa pun -
Salinan kode adalah sebagai berikut:
<skrip src = "js/myapp.js"> </script>
Jika ditempatkan di <head>, itu akan memblokir semua pekerjaan rendering halaman, menyebabkan pengguna tetap dalam keadaan "layar putih kematian" sampai skrip dimuat dan dieksekusi. Script di akhir <body> hanya akan membiarkan pengguna melihat halaman statis tanpa vitalitas. Di mana rendering klien seharusnya tersebar dengan kontrol yang tidak efektif dan kotak kosong. Ambil test case -
Salinan kode adalah sebagai berikut:
<! Doctype html>
<Html>
<head lang = "en">
<meta charset = "UTF-8">
<title> async memuat skrip </iteme>
<skrip src = "js/test.js"> </script>
</head>
<body>
<div> saya konten </div>
<img src = "img/test.jpg">
</body>
</html>
Di antara mereka, konten di test.js -
Salinan kode adalah sebagai berikut:
Peringatan ('Saya kode skrip di kepala. Setelah mengeksekusi JS di sini, rendering konten tubuh dimulai!');
Kita akan melihat bahwa peringatan adalah titik jeda, dan saat ini, halaman kosong. Namun, ketahuilah bahwa seluruh halaman telah dimuat saat ini. Jika tubuh berisi tag untuk atribut SRC tertentu (seperti tag IMG di atas), browser telah mulai memuat konten yang relevan saat ini. Singkatnya, perlu dicatat bahwa waktu kerja mesin JS dan mesin rendering saling eksklusif (beberapa buku menyebutnya utas UI).
Oleh karena itu, kita membutuhkan bahwa skrip yang bertanggung jawab untuk membuat halaman terlihat lebih baik dan menggunakan lebih baik harus dimuat segera, dan skrip yang dapat dimuat nanti akan dimuat nanti.
1. Penundaan eksekusi skrip
Sekarang menjadi semakin populer untuk menempatkan skrip di akhir halaman <body>. Dengan cara ini, di satu sisi, pengguna dapat melihat halaman lebih cepat, dan di sisi lain, skrip dapat secara langsung mengoperasikan elemen DOM yang telah dimuat. "Pindah" ini adalah peningkatan besar untuk sebagian besar skrip. Model halaman adalah sebagai berikut -
Salinan kode adalah sebagai berikut:
<! Doctype html>
<Html>
<head lang = "en">
<!-Metadata dan Lembar Script Buka Di Sini->
<skrip src = "headscript.js"> </script>
</head>
<body>
<!-Konten ada di sini->
<skrip src = "bodyscript.js"> </script>
</body>
</html>
Ini sangat mempercepat waktu rendering halaman, tetapi ketahuilah bahwa ini dapat memberi pengguna kesempatan untuk berinteraksi dengan halaman sebelum bodyscript dimuat. Alasan mengapa browser tidak dapat memuat skrip sebelum memuat dokumen lengkap adalah hambatan besar untuk dokumen besar yang dikirimkan melalui koneksi lambat.
Idealnya, pemuatan skrip harus dilakukan secara bersamaan dengan pemuatan dokumen dan tidak mempengaruhi rendering DOM. Dengan cara ini, setelah dokumen siap, skrip dapat dijalankan karena skrip yang sesuai telah dimuat dalam urutan tag <script>.
Kita dapat mencapai persyaratan ini dengan menggunakan penundaan, yaitu,
Salinan kode adalah sebagai berikut:
<Script src = "DeferredScript.js"> </ptript>
Menambahkan atribut tundukan setara dengan memberi tahu browser: Harap mulai memuat skrip ini segera, tetapi harap tunggu sampai dokumen siap dan semua skrip dengan atribut tundukan telah selesai berjalan sebelum menjalankannya.
Dengan cara ini, menempatkan skrip penundaan di tag kepala akan membawa semua manfaat dari menempatkan skrip pada tag tubuh, dan itu dapat sangat meningkatkan kecepatan pemuatan dokumen besar. Mode halaman saat ini adalah -
Salinan kode adalah sebagai berikut:
<! Doctype html>
<Html>
<head lang = "en">
<!-Metadata dan Lembar Script Buka Di Sini->
<skrip src = "headscript.js"> </script>
<Script src = "DeferredScript.js" Defer> </script>
</head>
<body>
<!-Konten ada di sini->
</body>
</html>
Namun, tidak semua browser mendukung tunduk (untuk beberapa browser modern, jika Defer dinyatakan, skrip internal mereka tidak akan melakukan dokumen. Operasi rendering dan dom. Keduanya IE4+ mendukung atribut penundaan). Ini berarti bahwa jika Anda ingin memastikan bahwa skrip penundaan Anda dapat berjalan setelah dokumen dimuat, Anda harus merangkum kode semua skrip penundaan dalam struktur seperti $ (dokumen). Ini sepadan, karena hampir 97% pengunjung dapat menikmati manfaat pemuatan paralel, sementara 3% pengunjung lainnya masih dapat menggunakan javascript berfitur lengkap.
2. Paralelisasi skrip lengkap
Biarkan skrip dimuat dan dieksekusi satu langkah lebih cepat. Saya tidak ingin menunggu sampai skrip tundukan berjalan satu demi satu (Defer mengingatkan kita pada skenario antrian yang dipesan di mana dokumen diam -diam menunggu dokumen dimuat), dan saya tidak ingin menunggu sampai dokumen siap sebelum menjalankan skrip ini. Saya ingin memuat dan menjalankan skrip ini sesegera mungkin. Di sini kita memikirkan atribut async dari HTML5, tetapi ketahuilah bahwa itu adalah anarki yang kacau.
Misalnya, kami memuat dua skrip pihak ketiga yang sama sekali tidak relevan, dan halaman berjalan dengan baik tanpa mereka, dan tidak peduli siapa yang berjalan lebih dulu dan siapa yang berjalan nanti. Oleh karena itu, menggunakan atribut async pada skrip pihak ketiga ini setara dengan meningkatkan kecepatan berjalan mereka tanpa menghabiskan satu sen.
Atribut async baru ditambahkan ke HTML5. Fungsinya mirip dengan tunduk, yaitu, memungkinkan rendering dom saat mengunduh skrip. Namun, itu akan dieksekusi sesegera mungkin setelah mengunduh (mis., Mesin JS menganggur dan dieksekusi segera), dan tidak ada jaminan bahwa skrip akan dieksekusi secara berurutan. Mereka akan selesai sebelum acara Onload.
Firefox 3.6, Opera 10.5, IE 9, dan Chrome dan Safari terbaru semuanya mendukung atribut Async. Async dan Defer dapat digunakan pada saat yang sama, sehingga semua IE setelah IE 4 mendukung pemuatan asinkron, tetapi hati -hati bahwa async akan menimpa tunduk.
Maka model halaman saat ini adalah sebagai berikut -
Salinan kode adalah sebagai berikut:
<! Doctype html>
<Html>
<head lang = "en">
<!-Metadata dan Lembar Script Buka Di Sini->
<skrip src = "headscript.js"> </script>
<Script src = "DeferredScript.js" Defer> </script>
</head>
<body>
<!-Konten ada di sini->
<skrip src = "asyncscript1.js" async defer> </cript>
<skrip src = "asyncscript2.js" async Defer> </cript>
</body>
</html>
Perhatikan pesanan eksekusi di sini - setiap file skrip dimuat, kemudian headscript.js dieksekusi, dan kemudian defferedscript.js dimuat di latar belakang saat rendering dom. Kemudian, DefferedScript.js dan dua skrip asinkron akan dijalankan pada akhir rendering Dom. Perhatikan bahwa untuk browser yang mendukung atribut async, kedua skrip ini akan habis.
3. Pemuatan skrip yang dapat diprogram
Meskipun fungsi dari dua sifat skrip di atas sangat menarik, mereka tidak banyak digunakan karena masalah kompatibilitas. Karena itu, kami menggunakan skrip untuk memuat skrip lain lebih banyak. Misalnya, kami hanya ingin memuat skrip untuk pengguna yang memenuhi kondisi tertentu, yang merupakan "pemuatan malas" yang sering disebutkan.
Di tingkat API browser, ada dua cara yang masuk akal untuk merangkak dan menjalankan skrip server -
1> menghasilkan permintaan AJAX dan menggunakan fungsi eval untuk memproses respons
2> Masukkan tag <script> ke DOM
Metode yang terakhir lebih baik karena browser akan khawatir tentang menghasilkan permintaan HTTP untuk kami. Selain itu, eval juga memiliki beberapa masalah praktis: ruang lingkup bocor, debugging berantakan, dan juga dapat mengurangi kinerja. Oleh karena itu, jika Anda ingin memuat skrip bernama fitur.js, kami harus menggunakan kode seperti berikut:
Salinan kode adalah sebagai berikut:
var head = document.geteLementsbyTagname ('head') [0];
var skrip = document.createElement ('Script');
script.src = 'feature.js';
head.AppendChild (skrip);
Tentu saja, kita perlu berurusan dengan mendengarkan callback, dan spesifikasi HTML5 mendefinisikan properti onload yang dapat mengikat panggilan balik.
Salinan kode adalah sebagai berikut:
script.onload = function () {
console.log ('Script dimuat ...');
}
Namun, IE8 dan versi yang lebih lama tidak mendukung Onload, mereka mendukung OnReadyStateChange. Selain itu, masih banyak hal aneh untuk mengatasi kesalahan. Di sini, Anda dapat merujuk ke beberapa perpustakaan pemuatan berbasis sekolah yang populer, seperti labjs, yepnope, persyaratan, dll.
Sebagai berikut, saya merangkum file loadjs sederhana sendiri -
Salinan kode adalah sebagai berikut:
var loadjs = function (url, callback) {
var head = document.geteLementsbyTagname ('head') [0];
var skrip = document.createElement ('Script');
script.src = url;
script.type = "Teks/JavaScript";
head.AppendChild (skrip);
// Skrip
// IE9+ juga mendukung Onload of W3C Standard
var ua = navigator.useragent,
ua_version;
// IE6/7/8
if (/msie ([^;]+)/. test (ua)) {
ua_version = parsefloat (regexp ["$ 1"], 10);
if (ua_version <= 8) {
Script.onReadyStateChange = function () {
if (this.readystate == "dimuat") {
callback ();
}
}
} kalau tidak {
script.onload = function () {
callback ();
};
}
} kalau tidak {
script.onload = function () {
callback ();
};
}
};
Saya tidak akan berbicara tentang pemuatan skrip yang tidak sinkron di Document.write. Sekarang hanya sedikit orang yang melakukan ini karena perbedaan browser benar -benar luar biasa.
Perhatikan bahwa menggunakan objek gambar untuk memuat file JS secara tidak sinkron, kode JS di dalam tidak akan dieksekusi.
Akhirnya, mari kita bicara tentang skrip pemuatan asinkron di Persyaratan.
Persyaratan tidak menjamin skrip target untuk dijalankan secara berurutan, tetapi hanya memastikan bahwa pesanan lari mereka dapat memenuhi persyaratan ketergantungan masing -masing. Oleh karena itu, kami memastikan bahwa semua skrip dimuat secara paralel sesegera mungkin dan melaksanakannya secara tertib sesuai dengan topologi ketergantungan.
4. Ringkasan
OK, ketika sampai pada hal ini, pernyataan skrip pemuatan asinkron sudah berakhir. Izinkan saya berbicara tentang urutan optimasi di sini lagi -
1> Dengan cara tradisional, kami menggunakan tag skrip untuk secara langsung menanamkannya ke dalam dokumen HTML. Berikut dua situasi -
A> Embed ke dalam tag kepala - Hati -hati karena melakukan hal itu tidak akan mempengaruhi pemuatan paralel file sumber daya statis lainnya dalam konten dokumen. Ini mempengaruhi rendering konten dokumen, yaitu rendering DOM saat ini akan diblokir dan layar putih akan disajikan.
B> Embed di bagian bawah tag tubuh - Untuk menghindari fenomena layar putih, kami memberikan prioritas untuk membuat DOM dan kemudian menjalankan skrip, tetapi masalahnya muncul lagi. Mari kita bicara tentang pertanyaan pertama terlebih dahulu - jika konten dokumen DOM relatif besar, ikatan acara interaksi akan ditunda, dan pengalamannya akan sedikit lebih buruk. Tentu saja, kita perlu membuat skrip penting dieksekusi terlebih dahulu berdasarkan kebutuhan. Mari kita bicara tentang masalah kedua - karena file skrip sejauh bagian bawah tubuh, pemuatan skrip ini tertunda dibandingkan dengan skrip di kepala. Oleh karena itu, untuk bagian bawah tubuh, itu bukan titik akhir optimasi.
C> Tambahkan Atribut Disper - Kami berharap skrip akan dimuat secara paralel sesegera mungkin, dan kami masih akan memasukkan sekelompok skrip ini ke dalam kepala. Pemuatan skrip harus dilakukan secara bersamaan dengan pemuatan dokumen dan tidak mempengaruhi rendering DOM. Dengan cara ini, skrip dapat dijalankan setelah dokumen siap. Jadi ada atribut tunduk. Tetapi perhatikan kompatibilitasnya. Untuk browser yang tidak mendukung atribut tunduk, kita perlu merangkum kode dalam $ (dokumen). Buatlah seperti jQuery. Perlu dicatat bahwa semua skrip dengan atribut penundaan dieksekusi secara berurutan sesuai dengan urutan penampilan mereka, sehingga mereka juga disinkronkan secara ketat.
2> Poin sebelumnya adalah tentang skrip eksekusi sinkron (perhatikan bahwa proses pemuatan skrip ini paralel, tetapi perbedaan antara siapa yang memicu permintaan terlebih dahulu dan siapa yang kemudian memicu permintaan). Titik optimasi berikutnya adalah "skrip eksekusi paralel". Tentu saja, kita tahu bahwa pada suatu saat, hanya satu file JS yang dieksekusi. "Paralel" di sini berarti bahwa siapa pun yang memuat terlebih dahulu, selama mesin JS menganggur saat ini, itu akan segera dieksekusi. Optimalisasi di sini dibagi menjadi dua jenis -
a> Menambahkan properti async - memang dapat menyelesaikan titik optimasi yang kami sebutkan di atas, tetapi memiliki keterbatasan tinggi, yaitu, hanya untuk pemuatan naskah non -ketergantungan. Contoh yang paling tepat adalah memperkenalkan beberapa skrip pihak ketiga. Juga, kombinasi dengan atribut Deffer benar -benar masalah besar. Tentu saja, ia juga memiliki masalah kompatibilitas. Tiga masalah di atas telah menyebabkan aplikasi mereka yang jarang. Saat menggunakan async, Anda harus memperhatikan masalah ketergantungan.
B> Script memuat skrip - jelas, kami menggunakan ini untuk mencapai tujuan "eksekusi skrip paralel". Pada saat yang sama, kami juga memfasilitasi kontrol ketergantungan skrip, jadi kami menggunakan manajemen beban cerdas untuk pemuatan asinkron di kebutuhan.
Oke, itu saja.
Di sini, saya hanya berbicara tentang konten yang terkait dengan skrip pemuatan asinkron. Ada bagian lain dari konten, yang merupakan pemuatan tidak sinkron file gaya atau sumber daya statis lainnya. untuk dilanjutkan ......