Dans d'innombrables endroits en ligne, j'ai vu la recommandation d'inclure CSS avant JavaScript. Le raisonnement est généralement de cette forme :
Quand il s'agit de commander votre CSS et JavaScript, vous voulez que votre CSS vienne en premier. La raison en est que le thread de rendu possède toutes les informations de style dont il a besoin pour rendre la page. Si JavaScript inclut la priorité, le moteur JavaScript doit tout analyser avant de passer à l'ensemble de ressources suivant. Cela signifie que le fil de rendu ne peut pas afficher complètement la page, car il n'a pas tous les styles dont il a besoin.
Mes tests réels révèlent quelque chose de tout à fait différent:
Mon harnais de test
J'utilise le script Ruby suivant pour générer des retards spécifiques pour diverses ressources:
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..."
}
Le mini-serveur ci-dessus me permet de définir des retards arbitraires pour les fichiers JavaScript (serveur et client) et des retards CSS arbitraires. Par exemple, http://10.0.0.50:8081/test.css?delay=500
me donne un délai de 500 ms pour transférer le CSS.
J'utilise la page suivante pour tester.
<!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>
Lorsque j'inclus le CSS en premier, la page prend 1,5 seconde pour s'afficher:
Lorsque j'inclus le JavaScript en premier, la page prend 1,4 seconde pour s'afficher:
J'obtiens des résultats similaires dans Chrome, Firefox et Internet Explorer. Dans Opera cependant, la commande n'a tout simplement pas d'importance.
Ce qui semble se produire, c'est que l'interpréteur JavaScript refuse de démarrer tant que tout le CSS n'est pas téléchargé. Il semble donc qu'avoir JavaScript inclut d'abord est plus efficace car le thread JavaScript obtient plus de temps d'exécution.
Suis-je en train de manquer quelque chose, la recommandation de placer les inclusions CSS avant les inclusions JavaScript n'est-elle pas correcte?
Il est clair que nous pourrions ajouter async ou utiliser setTimeout pour libérer le thread de rendu ou mettre le code JavaScript dans le pied de page, ou utiliser un chargeur JavaScript. Le point ici concerne la commande des bits JavaScript essentiels et des bits CSS dans la tête.
delay=400&jsdelay=1000
et delay=500
qui est loin de 100 ms ou 89 ms. Je suppose que je ne sais pas à quels chiffres vous faites référence.