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.
fonte
delay=400&jsdelay=1000
edelay=500
nem chega a 100ms ou 89ms. Acho que não estou claro a quais números você está se referindo.Respostas:
Esta é uma questão muito interessante. Eu sempre coloquei meus CSS
<link href="...">
antes dos JS<script src="...">
porque "Li uma vez que é melhor". Então, você está certo; é hora de fazermos uma pesquisa real!Eu configurei meu próprio equipamento de teste no Nó (código abaixo). Basicamente, eu:
<head>
executar<body>
execução, o que é análogoDOMReady
.Resultados
Primeiro, com o arquivo CSS atrasado em 500ms:
Em seguida, defino o jQuery para atrasar 500ms em vez do CSS:
Por fim, defino o jQuery e o CSS para atrasar em 500ms:
Conclusões
Primeiro, é importante observar que estou operando sob a suposição de que você possui scripts localizados no
<head>
documento (em oposição ao final do<body>
). Existem vários argumentos sobre o motivo pelo qual você pode vincular seus scripts no<head>
final do documento, mas isso está fora do escopo desta resposta. Isso é estritamente sobre se<script>
s deve ir antes de<link>
s no<head>
.Nos navegadores DESKTOP modernos, parece que vincular ao CSS primeiro nunca fornece um ganho de desempenho. Colocar CSS após o script gera um ganho trivial quando o CSS e o script estão atrasados, mas oferece grandes ganhos quando o CSS está atrasado. (Mostrado pelas
last
colunas no primeiro conjunto de resultados.)Dado que a vinculação ao último CSS não parece prejudicar o desempenho, mas pode proporcionar ganhos em determinadas circunstâncias, você deve vincular a folhas de estilo externas depois de vincular a scripts externos apenas em navegadores de desktop, se o desempenho de navegadores antigos não for uma preocupação. Leia sobre a situação móvel.
Por quê?
Historicamente, quando um navegador encontrava uma
<script>
tag apontando para um recurso externo, o navegador parava de analisar o HTML, recuperava o script, executava-o e continuava analisando o HTML. Por outro lado, se o navegador encontrasse um<link>
para uma folha de estilo externa, continuaria analisando o HTML enquanto buscava o arquivo CSS (em paralelo).Portanto, os conselhos amplamente repetidos para colocar as folhas de estilo em primeiro lugar - eles seriam baixados primeiro e o primeiro script a ser baixado poderia ser carregado em paralelo.
No entanto, navegadores modernos (incluindo todos os navegadores testados acima) implementaram a análise especulativa , em que o navegador "olha para a frente" no HTML e começa a baixar recursos antes de os scripts serem baixados e executados.
Em navegadores antigos sem análise especulativa, a colocação de scripts em primeiro lugar afetará o desempenho, pois eles não serão baixados em paralelo.
Suporte do navegador
A análise especulativa foi implementada pela primeira vez em: (junto com a porcentagem de usuários mundiais de navegadores de desktop que usam esta versão ou superior em janeiro de 2012)
No total, aproximadamente 85% dos navegadores de desktop em uso atualmente suportam carregamento especulativo. Colocar scripts antes do CSS terá uma penalidade de desempenho em 15% dos usuários em todo o mundo ; YMMV com base no público específico do seu site. (E lembre-se de que o número está diminuindo.)
Nos navegadores móveis, é um pouco mais difícil obter números definitivos simplesmente devido à heterogeneidade do navegador móvel e do cenário do sistema operacional. Como a renderização especulativa foi implementada no WebKit 525 (lançado em março de 2008) e praticamente todos os navegadores móveis que valem a pena são baseados no WebKit, podemos concluir que "a maioria" dos navegadores móveis deve suportá-lo. De acordo com o quirksmode , o iOS 2.2 / Android 1.0 usa o WebKit 525. Não tenho idéia de como é o Windows Phone.
No entanto, eu executei o teste no meu dispositivo Android 4 e, enquanto vi números semelhantes aos resultados da área de trabalho, liguei-o ao fantástico novo depurador remoto no Chrome para Android, e a guia Rede mostrou que o navegador estava realmente esperando para baixar o CSS até que os JavaScripts sejam completamente carregados - em outras palavras, mesmo a versão mais recente do WebKit para Android não parece suportar análise especulativa. Eu suspeito que ele possa estar desativado devido às restrições de CPU, memória e / ou rede inerentes aos dispositivos móveis.
Código
Perdoe a negligência - este foi o Q&D.
app.js
css.html
js.html
test.js
O jquery.js era o jquery-1.7.1.min.js
fonte
<head>
seu documento (em oposição ao final do<body>
)." Eu destacaria isso muito antes na resposta, como no topo. Incluir umscript
nohead
que se refere a um arquivo externo quase nunca é correto, de quase qualquer perspectiva (certamente não de desempenho). Não me lembro de ter feito isso na vida real. A linha ímpar ou duas do script embutido talvez, mas é tudo. O padrão, sem muito boas razões contrárias, deve ser o fim do corpo.Existem dois motivos principais para colocar o CSS antes do JavaScript.
Navegadores antigos (Internet Explorer 6-7, Firefox 2 etc.) bloqueariam todos os downloads subsequentes quando eles começassem a baixar um script. Portanto, se você
a.js
seguiu,b.css
eles são baixados sequencialmente: primeiro a então b. Se vocêb.css
seguiu,a.js
eles são baixados em paralelo para que a página seja carregada mais rapidamente.Nada é renderizado até que todas as folhas de estilo sejam baixadas - isso é verdade em todos os navegadores. Os scripts são diferentes - eles bloqueiam a renderização de todos os elementos DOM que estão abaixo da tag de script na página. Se você colocar seus scripts no HEAD, significa que a página inteira ficará impedida de renderizar até que todas as folhas de estilo e todos os scripts sejam baixados. Embora faça sentido bloquear toda a renderização para folhas de estilo (para que você obtenha o estilo correto na primeira vez e evite o flash do conteúdo sem estilo FOUC), não faz sentido bloquear a renderização da página inteira para scripts. Geralmente, os scripts não afetam nenhum elemento DOM ou apenas uma parte dos elementos DOM. É melhor carregar scripts o mais baixo possível na página, ou melhor ainda, carregá-los de forma assíncrona.
É divertido criar exemplos com o Cuzillion . Por exemplo, esta página possui um script no HEAD, para que a página inteira fique em branco até que o download seja concluído. No entanto, se movermos o script para o final do bloco BODY, o cabeçalho da página será renderizado, pois esses elementos DOM ocorrem acima da tag SCRIPT, como você pode ver nesta página .
fonte
async
atributo, que Steve está recomendando aqui quando diz "ainda melhor carregá-los de forma assíncrona" - stackoverflow.com/questions/1834077/…@import
diretivas?jQuery
+jQuery UI
+$(document).ready(function () { });
no final da página? Funcionará sempre como esperado?Eu não enfatizaria muito os resultados que você obteve, acredito que seja subjetivo, mas tenho um motivo para explicar que é melhor inserir CSS antes de js.
Durante o carregamento do seu site, há dois cenários que você vê:
CASO 1: tela branca> site sem estilo> site com estilo> interação> site com estilo e interativo
CASO 2: tela branca> site sem estilo> interação> site com estilo> site com estilo e interativo
Sinceramente, não consigo imaginar alguém escolhendo o Caso 2. Isso significaria que os visitantes que usam conexões lentas com a Internet se deparam com um site sem estilo, que lhes permite interagir com ele usando Javascript (já que ele já está carregado). Além disso, a quantidade de tempo gasto em um site não estilizado seria maximizada dessa maneira. Por que alguém iria querer isso?
Também funciona melhor como estados jQuery
Quando os arquivos são carregados na ordem errada (primeiro JS e depois CSS), qualquer código Javascript que dependa das propriedades definidas nos arquivos CSS (por exemplo, a largura ou a altura de uma div) não será carregado corretamente. Parece que, com a ordem de carregamento incorreta, as propriedades corretas são 'algumas vezes' conhecidas pelo Javascript (talvez isso seja causado por uma condição de corrida?). Esse efeito parece maior ou menor, dependendo do navegador usado.
fonte
Seus testes foram realizados no seu computador pessoal ou em um servidor da web? É uma página em branco ou é um sistema on-line complexo com imagens, bancos de dados etc.? Seus scripts estão executando uma ação simples de evento flutuante ou são um componente essencial para a renderização e interação do seu site com o usuário? Há várias coisas a considerar aqui, e a relevância dessas recomendações quase sempre se torna regras quando você se aventura no desenvolvimento da Web de alto calibre.
O objetivo da regra "colocar folhas de estilo na parte superior e scripts na parte inferior" é que, em geral, é a melhor maneira de obter uma renderização progressiva ideal , o que é essencial para a experiência do usuário.
Tudo o mais à parte: supondo que seu teste seja válido e você realmente esteja produzindo resultados contrários às regras populares, não seria nenhuma surpresa. Todo site (e tudo o que é necessário para que tudo apareça na tela do usuário) é diferente e a Internet está em constante evolução.
fonte
Eu incluo arquivos CSS antes do Javascript por um motivo diferente.
Se meu Javascript precisar fazer o dimensionamento dinâmico de algum elemento da página (para os casos de canto em que o CSS é realmente principal na parte de trás), carregar o CSS depois que o JS estiver sendo movido pode levar a condições de corrida, onde o elemento é redimensionado antes dos estilos CSS são aplicados e, portanto, parecem estranhos quando os estilos finalmente entram em ação. Se eu carregar o CSS de antemão, posso garantir que as coisas sejam executadas na ordem desejada e que o layout final seja o que eu quero que seja.
fonte
A recomendação para incluir CSS antes do JavaScript é inválida?
Não se você tratá-lo simplesmente como uma recomendação. Mas se você tratá-lo como uma regra rígida e rápida? Sim, é inválido.
De https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded
Parece que você precisa saber do que cada script se baseia e garantir que a execução do script seja adiada até após o evento de conclusão correto. Se o script se basear apenas no DOM, ele poderá continuar em ondomready / domcontentloaded, se depender de imagens a serem carregadas ou folhas de estilo a serem aplicadas, se eu ler a referência acima corretamente, esse código deverá ser adiado até o evento onload.
Eu não acho que um tamanho de meia serve para todos, mesmo que seja assim que eles são vendidos e eu sei que um tamanho de sapato não serve para todos. Eu não acho que exista uma resposta definitiva para carregar primeiro, estilos ou script. É mais uma decisão caso a caso do que deve ser carregado em que ordem e o que pode ser adiado até mais tarde como não estando no "caminho crítico".
Para falar com o observador que comentou que é melhor adiar a capacidade do usuário de interagir até que a folha fique bonita. Existem muitos de vocês por aí e você irrita seus colegas que sentem o contrário. Eles chegaram a um site para atingir um objetivo e os atrasos em sua capacidade de interagir com um site enquanto aguardam por coisas que não importam para terminar o carregamento são muito frustrantes. Não estou dizendo que você está errado, apenas que você deve estar ciente de que existe outra facção que não compartilha sua prioridade.
Esta pergunta se aplica particularmente a todos os anúncios colocados em sites. Eu adoraria que os autores do site processassem apenas divs de espaço reservado para o conteúdo do anúncio e certificassem que o site fosse carregado e interativo antes de injetar os anúncios em um evento onload. Mesmo assim, eu gostaria de ver os anúncios carregados em série, em vez de todos de uma vez, porque eles afetam minha capacidade de rolar o conteúdo do site enquanto os anúncios inchados estão sendo carregados. Mas esse é apenas o ponto de vista de uma pessoa.
fonte
Atualizado 16/12/2017
Eu não tinha certeza sobre os testes no OP. Decidi experimentar um pouco e acabei rebentando alguns dos mitos.
Isso não é mais verdade . Dê uma olhada na cascata gerada pelo Chrome 63:
Isto está incorreto . A folha de estilo não vai bloquear download, mas ele irá bloquear a execução do script ( pequena explicação aqui ). Veja o gráfico de desempenho gerado pelo Chrome 63:
Tendo em mente o acima exposto, os resultados no OP podem ser explicados da seguinte maneira:
CSS primeiro:
JS Primeiro:
fonte
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/… Por que a mesma suposição não se aplica no caso de JS primeiro? Não faz muito sentido para mim, a ordem do JS executado não diz nada sobre seu objetivo.Não sei exatamente como o seu teste 'renderiza' o tempo que você usa no script java. No entanto, considere isso
Uma página do seu site tem 50k, o que não é razoável. O usuário está na costa leste enquanto o servidor está no oeste. Definitivamente, o MTU não é 10k; portanto, haverá algumas viagens para frente e para trás. Pode demorar 1/2 segundo para receber sua página e folhas de estilo. Normalmente (para mim) javascript (via plugin jquery e outros) são muito mais que CSS. Também existe o que acontece quando a sua conexão à Internet é interrompida no meio da página, mas vamos ignorar isso (acontece ocasionalmente e acredito que o css é processado, mas não tenho 100% de certeza).
Como o css está na cabeça, pode haver conexões adicionais para obtê-lo, o que significa que ele pode terminar potencialmente antes da página. De qualquer forma, durante o tipo que o restante da página leva e nos arquivos javascript (que são muitos mais bytes), a página não tem um estilo, o que torna o site / conexão lento.
MESMO QUE o intérprete JS se recuse a iniciar até que o CSS termine o tempo necessário para baixar o código javascript, especialmente quando o servidor estiver longe do corte em tempo de css, o que fará com que o site não pareça bonito.
É uma pequena otimização, mas essa é a razão.
fonte
Aqui está um resumo de todas as principais respostas acima (ou talvez abaixo mais tarde :)
Para navegadores modernos, coloque o css onde quiser. Eles analisariam seu arquivo html (que eles chamam de análise especulativa ) e começariam a baixar o css em paralelo com a análise html.
Para navegadores antigos, continue colocando o CSS no topo (se você não quiser mostrar uma página nua, mas interativa primeiro).
Para todos os navegadores, coloque o javascript o mais abaixo possível na página, pois ele interromperá a análise do seu html. De preferência, faça o download de forma assíncrona (ou seja, chamada ajax)
Além disso, existem alguns resultados experimentais para um caso específico que afirma que colocar o javascript em primeiro lugar (em oposição à sabedoria tradicional de colocar o CSS em primeiro lugar) oferece melhor desempenho, mas não há um raciocínio lógico para ele e falta validação quanto à aplicabilidade generalizada, para que você possa ignorá-lo por enquanto.
Então, para responder à pergunta: Sim. A recomendação para incluir o CSS antes do JS é inválida para os navegadores modernos. Coloque o CSS onde quiser e coloque o JS no final, tanto quanto possível.
fonte
Steve Souders já deu uma resposta definitiva, mas ...
Gostaria de saber se há algum problema com o teste original de Sam e com a repetição de Josh.
Ambos os testes parecem ter sido realizados em conexões de baixa latência, onde a configuração da conexão TCP terá um custo trivial.
Como isso afeta o resultado do teste Eu não tenho certeza e gostaria de ver as cascatas para os testes em uma conexão de latência 'normal', mas ...
O primeiro arquivo baixado deve obter a conexão usada para a página html, e o segundo arquivo baixado obtém a nova conexão. (Liberar o início altera essa dinâmica, mas isso não está sendo feito aqui)
Nos navegadores mais novos, a segunda conexão TCP é aberta especulativamente, de modo que a sobrecarga da conexão é reduzida / desaparece; em navegadores antigos, isso não é verdade e a segunda conexão terá a sobrecarga de ser aberta.
Como / se isso afeta o resultado dos testes, não tenho certeza.
fonte
Eu acho que isso não será verdade para todos os casos. Porque o css baixará paralelo, mas o js não pode. Considere para o mesmo caso,
Em vez de ter um css único, pegue 2 ou 3 arquivos css e experimente-os desta maneira,
1) css..css..js 2) css..js..css 3) js..css..css
Tenho certeza que o css..css..js dará um resultado melhor do que todos os outros.
fonte
Devemos ter em mente que os novos navegadores funcionaram em seus mecanismos Javascript, analisadores e assim por diante, otimizando problemas comuns de código e marcação de uma maneira que os problemas enfrentados em navegadores antigos como <= IE8 não sejam mais relevantes, não apenas com no que diz respeito à marcação, mas também ao uso de variáveis JavaScript, seletores de elementos etc. Posso ver em um futuro não tão distante uma situação em que a tecnologia chegou a um ponto em que o desempenho não é mais um problema.
fonte
Pessoalmente, eu não daria muita ênfase a essa "sabedoria popular". O que pode ter sido verdade no passado pode muito bem não ser verdade agora. Eu assumiria que todas as operações relacionadas à interpretação e renderização de uma página da Web são totalmente assíncronas ("buscar" algo e "agir sobre ele" são duas coisas totalmente diferentes que podem estar sendo manipuladas por diferentes threads etc. ) e em qualquer caso, completamente fora do seu controle ou da sua preocupação.
Eu colocaria referências CSS na parte "head" do documento, juntamente com quaisquer referências a scripts externos. (Alguns scripts podem exigir que sejam colocados no corpo e, se houver, obrigam.)
Além disso ... se você observar que "isso parece ser mais rápido / mais lento que isso, neste / naquele navegador", trate essa observação como uma curiosidade interessante, mas irrelevante, e não permita que ela influencie suas decisões de design. Muitas coisas mudam rápido demais. (Alguém quer apostar em quantos minutos serão necessários até a equipe do Firefox lançar outro lançamento intermediário de seu produto? Sim, eu também não.)
fonte