In innumerevoli posti online ho visto la raccomandazione di includere CSS prima di JavaScript. Il ragionamento è generalmente, di questa forma :
Quando si tratta di ordinare CSS e JavaScript, si desidera che il CSS venga prima di tutto. Il motivo è che il thread di rendering ha tutte le informazioni di stile necessarie per eseguire il rendering della pagina. Se JavaScript include prima di tutto, il motore JavaScript deve analizzare tutto prima di continuare con il prossimo set di risorse. Ciò significa che il thread di rendering non può mostrare completamente la pagina, poiché non ha tutti gli stili di cui ha bisogno.
I miei test effettivi rivelano qualcosa di completamente diverso:
Il mio cablaggio di prova
Uso il seguente script Ruby per generare ritardi specifici per varie risorse:
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..."
}
Il mini server sopra riportato mi consente di impostare ritardi arbitrari per i file JavaScript (sia server che client) e ritardi CSS arbitrari. Ad esempio, http://10.0.0.50:8081/test.css?delay=500
mi dà un ritardo di 500 ms nel trasferimento del CSS.
Uso la pagina seguente per testare.
<!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>
Quando includo prima il CSS, il rendering della pagina richiede 1,5 secondi:
Quando includo prima JavaScript, la pagina impiega 1,4 secondi per il rendering:
Ottengo risultati simili in Chrome, Firefox e Internet Explorer. In Opera, tuttavia, l'ordinamento semplicemente non ha importanza.
Ciò che sembra accadere è che l'interprete JavaScript si rifiuta di iniziare fino a quando non viene scaricato tutto il CSS. Quindi, sembra che avere JavaScript includa prima sia più efficiente poiché il thread JavaScript ottiene più tempo di esecuzione.
Mi sto perdendo qualcosa, la raccomandazione di inserire CSS include prima di JavaScript non è corretta?
È chiaro che potremmo aggiungere asincroni o utilizzare setTimeout per liberare il thread di rendering o inserire il codice JavaScript nel piè di pagina o utilizzare un caricatore JavaScript. Il punto qui è sull'ordinamento di bit JavaScript essenziali e bit CSS nella testa.
delay=400&jsdelay=1000
e delay=500
non è vicino a 100ms o 89ms. Immagino di non essere chiaro a quali numeri ti riferisci.