Em inúmeros locais online, vi a recomendação de incluir CSS antes do JavaScript. O raciocínio é geralmente, desta forma :
Quando se trata de pedir seu CSS e JavaScript, você deseja que seu CSS seja o primeiro. O motivo é que o encadeamento de renderização possui todas as informações de estilo necessárias para renderizar a página. Se o JavaScript incluir o primeiro, o mecanismo JavaScript precisará analisar tudo antes de continuar no próximo conjunto de recursos. Isso significa que o encadeamento de renderização não pode mostrar completamente a página, pois não possui todos os estilos necessários.
Meu teste real revela algo bem diferente:
Meu equipamento de teste
Eu uso o seguinte script Ruby para gerar atrasos específicos para vários recursos:
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..."
}
O mini servidor acima permite definir atrasos arbitrários para arquivos JavaScript (servidor e cliente) e atrasos arbitrários em CSS. Por exemplo, http://10.0.0.50:8081/test.css?delay=500
me dá um atraso de 500 ms na transferência do CSS.
Eu uso a página a seguir para testar.
<!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 incluo o CSS primeiro, a página leva 1,5 segundos para renderizar:
Quando incluo o JavaScript primeiro, a página leva 1,4 segundos para renderizar:
Eu obtenho resultados semelhantes no Chrome, Firefox e Internet Explorer. No Opera, no entanto, a ordenação simplesmente não importa.
O que parece estar acontecendo é que o intérprete JavaScript se recusa a iniciar até que todo o CSS seja baixado. Portanto, parece que ter o JavaScript incluído primeiro é mais eficiente, pois o encadeamento do JavaScript ganha mais tempo de execução.
Estou faltando alguma coisa, a recomendação para colocar CSS inclui antes de JavaScript não está correta?
É claro que poderíamos adicionar async ou usar setTimeout para liberar o encadeamento de renderização ou colocar o código JavaScript no rodapé ou usar um carregador JavaScript. O ponto aqui é sobre a ordenação de bits JavaScript essenciais e CSS na cabeça.
delay=400&jsdelay=1000
e delay=500
nem chega a 100ms ou 89ms. Acho que não estou claro a quais números você está se referindo.