Di banyak tempat online saya telah melihat rekomendasi untuk memasukkan CSS sebelum JavaScript. Alasannya secara umum, dari bentuk ini :
Ketika datang untuk memesan CSS dan JavaScript Anda, Anda ingin CSS Anda yang lebih dulu. Alasannya adalah bahwa thread rendering memiliki semua informasi gaya yang diperlukan untuk membuat halaman. Jika JavaScript termasuk yang diutamakan, mesin JavaScript harus menguraikan semuanya sebelum melanjutkan ke rangkaian sumber daya berikutnya. Ini berarti untaian rendering tidak dapat sepenuhnya menampilkan halaman, karena tidak memiliki semua gaya yang dibutuhkan.
Pengujian saya yang sebenarnya mengungkapkan sesuatu yang sangat berbeda:
Uji harness saya
Saya menggunakan skrip Ruby berikut untuk menghasilkan penundaan spesifik untuk berbagai sumber daya:
require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'
require 'date'
class Handler < EventMachine::Connection
include EventMachine::HttpServer
def process_http_request
resp = EventMachine::DelegatedHttpResponse.new( self )
return unless @http_query_string
path = @http_path_info
array = @http_query_string.split("&").map{|s| s.split("=")}.flatten
parsed = Hash[*array]
delay = parsed["delay"].to_i / 1000.0
jsdelay = parsed["jsdelay"].to_i
delay = 5 if (delay > 5)
jsdelay = 5000 if (jsdelay > 5000)
delay = 0 if (delay < 0)
jsdelay = 0 if (jsdelay < 0)
# Block which fulfills the request
operation = proc do
sleep delay
if path.match(/.js$/)
resp.status = 200
resp.headers["Content-Type"] = "text/javascript"
resp.content = "(function(){
var start = new Date();
while(new Date() - start < #{jsdelay}){}
})();"
end
if path.match(/.css$/)
resp.status = 200
resp.headers["Content-Type"] = "text/css"
resp.content = "body {font-size: 50px;}"
end
end
# Callback block to execute once the request is fulfilled
callback = proc do |res|
resp.send_response
end
# Let the thread pool (20 Ruby threads) handle request
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine::start_server("0.0.0.0", 8081, Handler)
puts "Listening..."
}
Server mini di atas memungkinkan saya untuk mengatur penundaan sewenang-wenang untuk file JavaScript (baik server dan klien) dan penundaan CSS sewenang-wenang. Misalnya, http://10.0.0.50:8081/test.css?delay=500
beri saya penundaan 500 ms saat mentransfer CSS.
Saya menggunakan halaman berikut untuk menguji.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script type='text/javascript'>
var startTime = new Date();
</script>
<link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet">
<script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&jsdelay=1000"></script>
</head>
<body>
<p>
Elapsed time is:
<script type='text/javascript'>
document.write(new Date() - startTime);
</script>
</p>
</body>
</html>
Ketika saya memasukkan CSS terlebih dahulu, halaman membutuhkan 1,5 detik untuk merender:
Ketika saya memasukkan JavaScript terlebih dahulu, halaman membutuhkan 1,4 detik untuk merender:
Saya mendapatkan hasil yang serupa di Chrome, Firefox dan Internet Explorer. Namun di Opera, pemesanan tidak masalah.
Apa yang tampaknya terjadi adalah bahwa penerjemah JavaScript menolak untuk memulai sampai semua CSS diunduh. Jadi, tampaknya memiliki JavaScript yang disertakan terlebih dahulu lebih efisien karena utas JavaScript semakin lama berjalan.
Apakah saya kehilangan sesuatu, apakah rekomendasi untuk memasukkan CSS sebelum JavaScript termasuk tidak benar?
Jelas bahwa kita dapat menambahkan async atau menggunakan setTimeout untuk membebaskan utas render atau meletakkan kode JavaScript di footer, atau menggunakan loader JavaScript. Intinya di sini adalah tentang pemesanan bit JavaScript penting dan bit CSS di kepala.
sumber
delay=400&jsdelay=1000
dandelay=500
yang mana dekat 100ms atau 89ms. Saya kira saya tidak jelas nomor mana yang Anda maksud.Jawaban:
Ini pertanyaan yang sangat menarik. Saya selalu meletakkan CSS saya
<link href="...">
sebelum JS saya<script src="...">
karena "Saya pernah membaca bahwa itu lebih baik." Jadi kamu benar; sudah saatnya kita melakukan penelitian yang sebenarnya!Saya mengatur test harness saya sendiri di Node (kode di bawah). Pada dasarnya, saya:
<head>
menjalankan<body>
untuk dieksekusi, yang analog denganDOMReady
.Hasil
Pertama, dengan file CSS tertunda sebanyak 500 ms:
Selanjutnya, saya mengatur jQuery untuk menunda 500ms daripada CSS:
Akhirnya, saya menetapkan kedua jQuery dan CSS untuk menunda oleh 500ms:
Kesimpulan
Pertama, penting untuk dicatat bahwa saya beroperasi di bawah asumsi bahwa Anda memiliki skrip yang terletak di dalam
<head>
dokumen Anda (sebagai lawan dari akhir<body>
). Ada berbagai argumen tentang mengapa Anda mungkin menautkan ke skrip Anda di<head>
bagian akhir dokumen, tetapi itu di luar cakupan jawaban ini. Ini hanya tentang apakah<script>
s harus pergi sebelum<link>
s di<head>
.Di peramban DESKTOP modern, sepertinya menautkan ke CSS terlebih dahulu tidak pernah memberikan peningkatan kinerja. Menempatkan CSS setelah skrip memberi Anda jumlah keuntungan sepele saat CSS dan skrip ditunda, tetapi memberi Anda keuntungan besar saat CSS tertunda. (Ditunjukkan oleh
last
kolom di set hasil pertama.)Mengingat bahwa menautkan ke CSS terakhir tampaknya tidak mengganggu kinerja tetapi dapat memberikan keuntungan dalam keadaan tertentu, Anda harus menautkan ke stylesheet eksternal setelah Anda menautkan ke skrip eksternal hanya pada browser desktop jika kinerja browser lama tidak menjadi masalah. Baca terus untuk situasi seluler.
Mengapa?
Secara historis, ketika browser menemukan
<script>
tag yang menunjuk ke sumber daya eksternal, browser akan berhenti mem-parsing HTML, mengambil skrip, menjalankannya, lalu melanjutkan mem-parsing HTML. Sebaliknya, jika browser menemukan<link>
untuk stylesheet eksternal, itu akan melanjutkan penguraian HTML saat mengambil file CSS (secara paralel).Oleh karena itu, saran yang diulang secara luas untuk mengutamakan stylesheet - mereka akan unduh terlebih dahulu, dan skrip pertama untuk mengunduh dapat dimuat secara paralel.
Namun, browser modern (termasuk semua browser yang saya uji dengan di atas) telah menerapkan penguraian spekulatif , di mana browser "melihat ke depan" dalam HTML dan mulai mengunduh sumber daya sebelum skrip mengunduh dan mengeksekusi.
Di browser lama tanpa penguraian spekulatif, menempatkan skrip terlebih dahulu akan memengaruhi kinerja karena mereka tidak akan mengunduh secara paralel.
Dukungan Browser
Penguraian spekulatif pertama kali diterapkan di: (bersama dengan persentase pengguna browser desktop di seluruh dunia menggunakan versi ini atau lebih besar pada Jan 2012)
Secara total, sekitar 85% browser desktop yang digunakan saat ini mendukung pemuatan spekulatif. Menempatkan skrip sebelum CSS akan memiliki penalti kinerja pada 15% pengguna secara global ; YMMV berdasarkan audiens spesifik situs Anda. (Dan ingat angka itu menyusut.)
Pada peramban seluler, agak sulit untuk mendapatkan angka pasti hanya karena seberapa heterogennya peramban seluler dan lanskap OS. Karena rendering spekulatif diterapkan di WebKit 525 (dirilis Mar 2008), dan hampir setiap browser seluler yang berharga didasarkan pada WebKit, kita dapat menyimpulkan bahwa "sebagian besar" browser seluler harus mendukungnya. Menurut quirksmode , iOS 2.2 / Android 1.0 menggunakan WebKit 525. Saya tidak tahu seperti apa Windows Phone itu.
Namun, saya menjalankan tes pada perangkat Android 4 saya, dan sementara saya melihat angka yang mirip dengan hasil desktop, saya menghubungkannya dengan debugger jarak jauh baru yang fantastis di Chrome untuk Android, dan tab Network menunjukkan bahwa browser benar-benar menunggu untuk mengunduh. CSS hingga JavaScripts dimuat sepenuhnya - dengan kata lain, bahkan versi terbaru WebKit untuk Android tampaknya tidak mendukung penguraian spekulatif. Saya menduga itu mungkin dimatikan karena CPU, memori, dan / atau kendala jaringan yang melekat pada perangkat seluler.
Kode
Maafkan kecerobohan - ini adalah Q&P.
app.js
css.html
js.html
test.js
jquery.js adalah jquery-1.7.1.min.js
sumber
<head>
dokumen Anda (sebagai lawan dari akhir<body>
)." Saya akan menyoroti itu jauh sebelumnya dalam jawaban, seperti di atas. Termasukscript
dalamhead
yang merujuk ke file eksternal hampir tidak pernah benar, dari hampir semua perspektif (tentu saja bukan kinerja). Saya tidak ingat pernah melakukannya di kehidupan nyata. Mungkin satu atau dua baris skrip inline , tapi hanya itu. Defaultnya, tanpa alasan yang sangat bertentangan, harus menjadi akhir dari tubuh.Ada dua alasan utama untuk menempatkan CSS sebelum JavaScript.
Browser lama (Internet Explorer 6-7, Firefox 2, dll.) Akan memblokir semua unduhan berikutnya ketika mereka mulai mengunduh skrip. Jadi, jika Anda
a.js
mengikutib.css
mereka diunduh secara berurutan: pertama a lalu b. Jika Andab.css
mengikutia.js
mereka diunduh secara paralel sehingga halaman dimuat lebih cepat.Tidak ada yang dirender sampai semua stylesheet diunduh - ini benar di semua browser. Skrip berbeda - mereka memblokir rendering semua elemen DOM yang berada di bawah tag skrip di halaman. Jika Anda meletakkan skrip Anda di HEAD maka itu berarti seluruh halaman diblokir dari rendering sampai semua stylesheet dan semua skrip diunduh. Meskipun masuk akal untuk memblokir semua rendering untuk stylesheet (sehingga Anda mendapatkan gaya yang benar pertama kali dan menghindari flash konten yang tidakstyle FOUC), tidak masuk akal untuk memblokir rendering seluruh halaman untuk skrip. Seringkali skrip tidak memengaruhi elemen DOM atau hanya sebagian elemen DOM. Cara terbaik untuk memuat skrip serendah mungkin di halaman, atau bahkan lebih baik memuatnya secara tidak sinkron.
Sangat menyenangkan untuk membuat contoh dengan Cuzillion . Misalnya, halaman ini memiliki skrip di HEAD sehingga seluruh halaman kosong sampai selesai mengunduh. Namun, jika kita memindahkan skrip ke ujung BODY, blok header halaman di-render karena elemen-elemen DOM tersebut muncul di atas tag SCRIPT, seperti yang dapat Anda lihat di halaman ini .
sumber
async
atribut, yang direkomendasikan Steve di sini ketika ia mengatakan "lebih baik memuatnya secara tidak sinkron" - stackoverflow.com/questions/1834077/…@import
arahan?jQuery
+jQuery UI
+$(document).ready(function () { });
di akhir halaman? Apakah akan selalu bekerja seperti yang diharapkan?Saya tidak akan terlalu menekankan pada hasil yang Anda dapatkan, saya percaya itu subjektif, tapi saya punya alasan untuk menjelaskan Anda bahwa lebih baik dimasukkan ke dalam CSS sebelum js.
Selama memuat situs web Anda, ada dua skenario yang akan Anda lihat:
KASUS 1: layar putih> situs unstyled> situs ditata> interaksi> gaya dan website interaktif
KASUS 2: layar putih> situs unstyled> interaksi> situs ditata> bergaya dan interaktif situs
saya jujur tidak bisa membayangkan orang memilih Kasus 2. Ini berarti bahwa pengunjung yang menggunakan koneksi internet lambat akan dihadapkan dengan situs web tanpa gaya, yang memungkinkan mereka untuk berinteraksi dengannya menggunakan Javascript (karena itu sudah dimuat). Selain itu, jumlah waktu yang dihabiskan untuk melihat situs web yang tidak bergaya akan dimaksimalkan dengan cara ini. Mengapa ada yang mau itu?
Ini juga berfungsi lebih baik sebagai status jQuery
Ketika file dimuat dalam urutan yang salah (JS pertama, lalu CSS), kode Javascript apa pun yang mengandalkan properti yang diatur dalam file CSS (misalnya lebar atau tinggi div) tidak akan dimuat dengan benar. Tampaknya dengan urutan pemuatan yang salah, properti yang benar 'terkadang' diketahui oleh Javascript (mungkin ini disebabkan oleh kondisi balapan?). Efek ini tampak lebih besar atau lebih kecil tergantung pada browser yang digunakan.
sumber
Apakah tes Anda dilakukan di komputer pribadi Anda, atau di server web? Itu adalah halaman kosong, atau apakah itu sistem online yang kompleks dengan gambar, database, dll.? Apakah skrip Anda melakukan hover event action sederhana, atau apakah itu komponen inti bagaimana situs web Anda membuat dan berinteraksi dengan pengguna? Ada beberapa hal yang perlu dipertimbangkan di sini, dan relevansi rekomendasi ini hampir selalu menjadi aturan ketika Anda menjelajah ke pengembangan web kaliber tinggi.
Tujuan dari "menempatkan stylesheet di bagian atas dan skrip di bagian bawah" aturan adalah, secara umum, itu adalah cara terbaik untuk mencapai rendering progresif yang optimal , yang sangat penting bagi pengalaman pengguna.
Selain itu: menganggap tes Anda valid, dan Anda benar-benar menghasilkan hasil yang bertentangan dengan aturan populer, itu tidak mengejutkan, sungguh. Setiap situs web (dan semua yang diperlukan untuk membuat semuanya muncul di layar pengguna) berbeda dan Internet terus berkembang.
sumber
Saya menyertakan file CSS sebelum Javascript untuk alasan yang berbeda.
Jika Javascript saya perlu melakukan pengukuran dinamis dari beberapa elemen halaman (untuk kasus sudut di mana CSS benar-benar utama di belakang) maka memuat CSS setelah JS russing dapat menyebabkan kondisi balapan, di mana elemen diubah ukurannya sebelum gaya CSS diterapkan dan dengan demikian terlihat aneh ketika gaya akhirnya masuk. Jika saya memuat CSS sebelumnya saya dapat menjamin bahwa semuanya berjalan dalam urutan yang dimaksudkan dan bahwa tata letak akhir adalah apa yang saya inginkan.
sumber
Apakah rekomendasi untuk memasukkan CSS sebelum JavaScript tidak valid?
Tidak jika Anda memperlakukannya hanya sebagai rekomendasi. Tetapi jika Anda memperlakukannya sebagai aturan yang keras dan cepat ?, ya, itu tidak valid.
Dari https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded
Tampaknya Anda perlu tahu apa yang diandalkan oleh setiap skrip dan memastikan bahwa eksekusi skrip ditunda hingga setelah acara penyelesaian yang tepat. Jika skrip hanya bergantung pada DOM, skrip dapat dilanjutkan di ondomready / domcontentloaded, jika itu bergantung pada gambar yang akan dimuat atau stylesheet yang akan diterapkan, maka jika saya membaca referensi di atas dengan benar, kode itu harus ditunda sampai peristiwa onload.
Saya tidak berpikir bahwa satu ukuran kaus kaki cocok untuk semua, meskipun itulah cara mereka dijual dan saya tahu bahwa satu ukuran sepatu tidak cocok untuk semua. Saya tidak berpikir bahwa ada jawaban pasti untuk memuat pertama, gaya atau skrip. Ini lebih merupakan kasus per kasus keputusan apa yang harus dimuat dalam urutan apa dan apa yang bisa ditunda sampai nanti karena tidak berada di "jalur kritis".
Untuk berbicara dengan pengamat yang berkomentar bahwa lebih baik untuk menunda kemampuan pengguna untuk berinteraksi sampai lembar itu cantik. Ada banyak dari Anda di luar sana dan Anda mengganggu rekan-rekan Anda yang merasakan hal sebaliknya. Mereka datang ke situs untuk mencapai tujuan dan menunda kemampuan mereka untuk berinteraksi dengan situs sambil menunggu hal-hal yang tidak masalah untuk menyelesaikan pemuatan sangat frustasi. Saya tidak mengatakan bahwa Anda salah, hanya bahwa Anda harus sadar bahwa ada faksi lain yang ada yang tidak berbagi prioritas Anda.
Pertanyaan ini terutama berlaku untuk semua iklan yang ditempatkan di situs web. Saya akan senang jika penulis situs hanya memberikan div placeholder untuk konten iklan dan memastikan bahwa situs mereka dimuat dan interaktif sebelum menyuntikkan iklan dalam acara onload. Bahkan kemudian saya ingin melihat iklan dimuat secara serial bukan sekaligus karena mereka memengaruhi kemampuan saya untuk bahkan menggulir konten situs saat iklan kembung dimuat. Tapi itu hanya sudut pandang satu orang.
sumber
Diperbarui 2017-12-16
Saya tidak yakin tentang tes di OP. Saya memutuskan untuk bereksperimen sedikit dan akhirnya menghancurkan beberapa mitos.
Ini tidak lagi benar . Lihatlah air terjun yang dihasilkan oleh Chrome 63:
Ini salah . Stylesheet tidak akan memblokir unduhan tetapi akan memblokir eksekusi skrip ( sedikit penjelasan di sini ). Lihat grafik kinerja yang dihasilkan oleh Chrome 63:
Dengan mengingat hal di atas, hasil dalam OP dapat dijelaskan sebagai berikut:
CSS Pertama:
JS First:
sumber
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load.
javascript.info/... Mengapa asumsi yang sama tidak berlaku untuk JS? Tidak masuk akal bagi saya, urutan eksekusi JS tidak mengatakan apa-apa tentang tujuan itu.Saya tidak begitu yakin bagaimana pengujian 'render' Anda saat menggunakan java script. Namun pertimbangkan ini
Satu halaman di situs Anda adalah 50k yang tidak masuk akal. Pengguna berada di pantai timur saat server Anda berada di barat. MTU jelas bukan 10rb sehingga akan ada beberapa perjalanan bolak-balik. Mungkin butuh 1/2 detik untuk menerima halaman dan stylesheet Anda. Biasanya javascript (untuk saya) (melalui plugin jquery dan semacamnya) lebih dari sekadar CSS. Ada juga apa yang terjadi ketika koneksi internet Anda tercekik di tengah-tengah halaman tetapi mari kita abaikan itu (itu terjadi pada saya sesekali dan saya percaya css merender tetapi saya tidak 100% yakin).
Karena css ada di kepala mungkin ada koneksi tambahan untuk mendapatkannya yang berarti berpotensi menyelesaikan sebelum halaman melakukannya. Bagaimanapun selama jenis sisa halaman mengambil dan file javascript (yang lebih banyak byte) halaman tidak di-style yang membuat situs / koneksi tampak lambat.
BAHKAN JIKA penerjemah JS menolak untuk memulai sampai CSS selesai waktu yang dibutuhkan untuk mengunduh kode javascript terutama ketika jauh dari server memotong waktu css yang akan membuat situs terlihat tidak cantik.
Ini optimasi kecil tapi itulah alasannya.
sumber
Berikut ini adalah RINGKASAN dari semua jawaban utama di atas (atau mungkin di bawah nanti :)
Untuk peramban modern, letakkan css di mana pun Anda suka. Mereka akan menganalisis file html Anda (yang mereka sebut parsing spekulatif ) dan mulai mengunduh css secara paralel dengan parsing html.
Untuk browser lama, terus letakkan css di atas (jika Anda tidak ingin menampilkan halaman yang telanjang tetapi interaktif terlebih dahulu).
Untuk semua browser, letakkan javascript sejauh mungkin di halaman, karena itu akan menghentikan penguraian html Anda. Lebih disukai, unduh secara asinkron (mis., Panggilan ajax)
Ada juga, beberapa hasil eksperimental untuk kasus tertentu yang mengklaim menempatkan javascript pertama (sebagai lawan dari kearifan tradisional menempatkan CSS pertama) memberikan kinerja yang lebih baik tetapi tidak ada alasan logis yang diberikan untuk itu, dan tidak memiliki validasi mengenai penerapan yang luas, sehingga Anda dapat abaikan saja untuk sekarang.
Jadi, untuk menjawab pertanyaan: Ya. Rekomendasi untuk menyertakan CSS sebelum JS tidak valid untuk browser modern. Letakkan CSS di mana pun Anda suka, dan letakkan JS di akhir, mungkin.
sumber
Steve Souders telah memberikan jawaban yang pasti tetapi ...
Saya bertanya-tanya apakah ada masalah dengan tes asli Sam dan pengulangan Josh.
Kedua tes tampaknya telah dilakukan pada koneksi latensi rendah di mana pengaturan koneksi TCP akan memiliki biaya sepele.
Bagaimana ini mempengaruhi hasil tes saya tidak yakin dan saya ingin melihat air terjun untuk tes melalui koneksi latensi 'normal' tapi ...
File pertama yang diunduh harus menggunakan koneksi yang digunakan untuk halaman html, dan file kedua yang diunduh akan mendapatkan koneksi baru. (Menyiram perubahan awal yang dinamis, tapi itu tidak dilakukan di sini)
Pada browser yang lebih baru, koneksi TCP kedua dibuka secara spekulatif sehingga overhead koneksi berkurang / hilang, pada browser lama ini tidak benar dan koneksi kedua akan memiliki overhead yang sedang dibuka.
Cukup bagaimana / jika ini mempengaruhi hasil tes saya tidak yakin.
sumber
Saya pikir ini tidak akan berlaku untuk semua kasus. Karena css akan mengunduh paralel tetapi js tidak bisa. Pertimbangkan untuk kasus yang sama,
Alih-alih memiliki css tunggal, ambil 2 atau 3 file css dan coba cara ini,
1) css..css..js 2) css..js..css 3) js..css..css
Saya yakin css..css..js akan memberikan hasil yang lebih baik daripada yang lainnya.
sumber
Kita harus ingat bahwa browser baru telah bekerja pada mesin Javascript mereka, parser mereka dan sebagainya, mengoptimalkan kode umum dan masalah markup sedemikian rupa sehingga masalah yang dialami pada browser kuno seperti <= IE8 tidak lagi relevan, tidak hanya dengan salam untuk markup tetapi juga untuk menggunakan variabel JavaScript, pemilih elemen dll. Saya bisa melihat di masa depan yang tidak terlalu jauh situasi di mana teknologi telah mencapai titik di mana kinerja tidak benar-benar masalah lagi.
sumber
Secara pribadi, saya tidak akan terlalu menekankan pada "kearifan rakyat". Apa yang mungkin benar di masa lalu mungkin tidak benar sekarang. Saya akan berasumsi bahwa semua operasi yang berkaitan dengan interpretasi dan rendering halaman web sepenuhnya tidak sinkron ("mengambil" sesuatu dan "menindaklanjutinya" adalah dua hal yang sepenuhnya berbeda yang mungkin ditangani oleh utas yang berbeda, dll. ), Dan dalam hal apa pun sepenuhnya di luar kendali Anda atau masalah Anda.
Saya akan meletakkan referensi CSS di bagian "head" dokumen, bersama dengan referensi ke skrip eksternal. (Beberapa skrip mungkin menuntut untuk ditempatkan di badan, dan jika demikian, mewajibkannya.)
Di luar itu ... jika Anda mengamati bahwa "ini tampaknya lebih cepat / lebih lambat dari itu, pada browser ini / itu," memperlakukan pengamatan ini sebagai keingintahuan yang menarik tetapi tidak relevan dan jangan biarkan itu memengaruhi keputusan desain Anda. Terlalu banyak hal berubah terlalu cepat. (Adakah yang mau bertaruh berapa menit sebelum tim Firefox mengeluarkan produk mereka untuk sementara waktu? Yup, saya juga.)
sumber