An unzähligen Stellen im Internet habe ich die Empfehlung gesehen, CSS vor JavaScript aufzunehmen. Die Argumentation hat im Allgemeinen folgende Form :
Wenn Sie CSS und JavaScript bestellen möchten, soll Ihr CSS an erster Stelle stehen. Der Grund dafür ist, dass der Rendering-Thread alle Stilinformationen enthält, die zum Rendern der Seite erforderlich sind. Wenn die JavaScript-Includes an erster Stelle stehen, muss die JavaScript-Engine alles analysieren, bevor Sie mit den nächsten Ressourcen fortfahren können. Dies bedeutet, dass der Rendering-Thread die Seite nicht vollständig anzeigen kann, da er nicht alle benötigten Stile enthält.
Meine eigentlichen Tests zeigen etwas ganz anderes:
Mein Testgeschirr
Ich verwende das folgende Ruby-Skript, um bestimmte Verzögerungen für verschiedene Ressourcen zu generieren:
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..."
}
Mit dem oben genannten Miniserver kann ich beliebige Verzögerungen für JavaScript-Dateien (sowohl Server als auch Client) und beliebige CSS-Verzögerungen festlegen. Zum Beispiel http://10.0.0.50:8081/test.css?delay=500
gibt mir eine 500 ms Verzögerung beim Übertragen des CSS.
Ich benutze die folgende Seite zum Testen.
<!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>
Wenn ich das CSS zuerst einbinde, dauert das Rendern der Seite 1,5 Sekunden:
Wenn ich zuerst JavaScript einbinde, dauert das Rendern der Seite 1,4 Sekunden:
Ich erhalte ähnliche Ergebnisse in Chrome, Firefox und Internet Explorer. In Opera spielt die Reihenfolge jedoch keine Rolle.
Was zu passieren scheint, ist, dass der JavaScript-Interpreter den Start verweigert, bis das gesamte CSS heruntergeladen ist. Es scheint also effizienter zu sein, JavaScript zuerst einzuschließen, da der JavaScript-Thread mehr Laufzeit erhält.
Fehlt mir etwas, ist die Empfehlung, CSS-Includes vor JavaScript-Includes zu platzieren, nicht korrekt?
Es ist klar, dass wir asynchron hinzufügen oder setTimeout verwenden können, um den Render-Thread freizugeben, den JavaScript-Code in die Fußzeile einzufügen oder einen JavaScript-Loader zu verwenden. Hier geht es um die Reihenfolge der wesentlichen JavaScript- und CSS-Bits im Kopf.
delay=400&jsdelay=1000
und delay=500
das ist nicht annähernd 100 ms oder 89 ms. Ich glaube, ich bin mir nicht sicher, auf welche Zahlen Sie sich beziehen.