Dipublikasikan: 31 Desember 2013
JavaScript memungkinkan kita untuk memodifikasi hampir semua aspek halaman: konten, penataan gaya, dan responsnya terhadap interaksi pengguna. Namun, JavaScript juga dapat memblokir konstruksi DOM dan menunda waktu laman dirender. Untuk menghasilkan kinerja yang optimal, jadikan JavaScript Anda asinkron dan tiadakan setiap JavaScript yang tidak penting dari jalur rendering penting.
Ringkasan
- JavaScript dapat melakukan kueri dan memodifikasi DOM dan CSSOM.
- Eksekusi JavaScript akan memblokir di CSSOM.
- JavaScript memblokir konstruksi DOM kecuali secara eksplisit dideklarasikan sebagai asinkron.
JavaScript adalah bahasa dinamis yang berjalan di browser dan memungkinkan kita untuk mengubah hampir setiap aspek dari cara kerja halaman: kita dapat memodifikasi konten dengan menambahkan dan menghapus elemen dari hierarki DOM; kita dapat memodifikasi properti CSSOM setiap elemen; kita dapat menangani input pengguna; dan banyak lagi. Untuk mengilustrasikan hal ini, lihat apa yang terjadi saat contoh "Hello World" sebelumnya diubah untuk menambahkan skrip inline singkat:
Critical Path: Script
Hello web performance students!
JavaScript memungkinkan kita mengakses DOM dan mengambil referensi ke simpul bentang tersembunyi; simpul ini mungkin tidak terlihat di pohon render, namun masih ada di DOM. Selanjutnya, bila memiliki referensinya, kita bisa mengubah teksnya (lewat .textContent), dan bahkan mengganti properti gaya tampilan yang dihitungnya dari "none" menjadi "inline". Sekarang halaman kita menampilkan "Halo siswa interaktif!".
JavaScript juga memungkinkan kita untuk membuat, menata gaya, menambahkan, dan membuang elemen baru di DOM. Secara teknis, keseluruhan halaman kita bisa berupa satu file JavaScript besar saja yang membuat dan menata gaya elemen satu per satu. Meskipun itu bisa dilakukan, dalam praktiknya menggunakan HTML dan CSS jauh lebih mudah. Di bagian kedua fungsi JavaScript, kita membuat elemen div yang baru, menetapkan materi teksnya, menggayakannya, dan menambahkannya ke tubuh.
Dengan hal itu, kita telah memodifikasi materi dan gaya CSS dari node DOM yang ada, dan menambahkan seluruh node yang baru ke dokumen. Laman kita tidak akan memenangkan penghargaan desain, tetapi laman menggambarkan kemampuan dan fleksibilitas yang ditawarkan JavaScript kepada kita.
Namun, meskipun JavaScript menawarkan banyak kemampuan kepada kita, banyak batasan tambahan yang ditimbulkan dalam hal bagaimana dan kapan laman dirender.
Pertama, perhatikan bahwa dalam contoh sebelumnya, skrip inline kita ada di bagian bawah halaman. Mengapa? Anda harus mencobanya sendiri, tetapi jika kita memindahkan skrip di atas elemen , Anda akan melihat bahwa skrip akan gagal dan mengeluh bahwa ia tidak dapat menemukan referensi ke elemen
dalam dokumen; yaitu,
getElementsByTagName('span')
menampilkan null
. Ini mendemonstrasikan properti penting: skrip kita dieksekusi pada titik penyisipan yang tepat di dalam dokumen. Saat parser HTML menemukan tag skrip, parser akan menjeda proses konstruksi DOM dan menghasilkan kontrol atas mesin JavaScript; setelah mesin JavaScript selesai dijalankan, browser selanjutnya melanjutkan dari tempat terakhir dan meneruskan konstruksi DOM.
Dengan kata lain, blok skrip kita tidak dapat menemukan elemen apa pun di bagian bawah halaman karena belum diproses! Atau, dengan kata lain: mengeksekusi skrip inline akan memblokir konstruksi DOM, yang juga akan menunda render awal.
Properti samar lainnya dari pengenalan skrip ke dalam halaman kita adalah skrip dapat membaca dan mengubah tidak hanya DOM, tetapi juga properti CSSOM. Faktanya, itulah yang sebenarnya kita lakukan dalam contoh kita ketika kita mengubah properti tampilan dari elemen bentang dari none ke inline. Hasil akhirnya? Sekarang kita memiliki kondisi race.
Bagaimana jika browser belum selesai mendownload dan mem-build CSSOM saat kita ingin menjalankan skrip? Jawabannya tidak terlalu bagus untuk performa: browser menunda eksekusi skrip dan konstruksi DOM hingga selesai mendownload dan membangun CSSOM.
Singkatnya, JavaScript menimbulkan banyak dependensi baru di antara eksekusi DOM, CSSOM, dan JavaScript. Hal ini dapat menyebabkan penundaan browser secara signifikan dalam pemrosesan dan rendering halaman pada layar:
- Lokasi skrip dalam dokumen sifatnya signifikan.
- Saat browser menemukan tag skrip, konstruksi DOM akan berhenti sementara hingga skrip selesai dieksekusi.
- JavaScript dapat melakukan kueri dan memodifikasi DOM dan CSSOM.
- Eksekusi JavaScript akan berhenti sementara hingga CSSOM siap.
Secara garis besarnya, "mengoptimalkan jalur rendering penting" mengacu pada pemahaman dan pengoptimalan grafik dependensi antara HTML, CSS, dan JavaScript.
Pemblokiran parser versus JavaScript asinkron
Secara default, eksekusi JavaScript adalah "pemblokiran parser": saat browser menemukan skrip dalam dokumen, browser harus menjeda konstruksi DOM, menyerahkan kontrol ke runtime JavaScript, dan membiarkan skrip dieksekusi sebelum melanjutkan dengan konstruksi DOM. Kita melihat aksinya pada skrip inline dalam contoh kita sebelumnya. Faktanya, skrip inline selalu memblokir parser kecuali jika Anda menulis kode tambahan untuk menunda eksekusinya.
Bagaimana dengan skrip yang disertakan menggunakan tag skrip? Ambil contoh sebelumnya dan ekstrak kode ke dalam file terpisah:
Critical Path: Script External
Hello web performance students!
app.js
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);
Baik kita menggunakan tag