Aqui está o que acontece quando um navegador carrega um site com uma <script>
tag:
- Busque a página HTML (por exemplo, index.html)
- Comece a analisar o HTML
- O analisador encontra uma
<script>
marca referenciando um arquivo de script externo.
- O navegador solicita o arquivo de script. Enquanto isso, o analisador bloqueia e para de analisar o outro HTML em sua página.
- Depois de algum tempo, o script é baixado e executado posteriormente.
- O analisador continua analisando o restante do documento HTML.
O passo 4 causa uma má experiência do usuário. Seu site basicamente pára de carregar até que você baixe todos os scripts. Se há algo que os usuários odeiam, está esperando o carregamento de um site.
Por que isso acontece?
Qualquer script pode inserir seu próprio HTML via document.write()
ou outras manipulações DOM. Isso implica que o analisador precisa esperar até que o script seja baixado e executado antes de poder analisar com segurança o restante do documento. Afinal, o script poderia ter inserido seu próprio HTML no documento.
No entanto, a maioria dos desenvolvedores de JavaScript não manipula mais o DOM enquanto o documento está sendo carregado. Em vez disso, eles esperam até o documento ser carregado antes de modificá-lo. Por exemplo:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script src="my-script.js"></script>
</head>
<body>
<div id="user-greeting">Welcome back, user</div>
</body>
</html>
Javascript:
// my-script.js
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready, i.e. when the document has been parsed
document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});
Como o seu navegador não sabe que o my-script.js não modifica o documento até que ele seja baixado e executado, o analisador para de analisar.
Recomendação antiquada
A abordagem antiga para resolver esse problema era colocar <script>
tags na parte inferior do seu <body>
, porque isso garante que o analisador não seja bloqueado até o final.
Essa abordagem tem seu próprio problema: o navegador não pode iniciar o download dos scripts até que todo o documento seja analisado. Para sites maiores com scripts e folhas de estilo grandes, a capacidade de fazer o download do script o mais rápido possível é muito importante para o desempenho. Se o seu site não carregar dentro de 2 segundos, as pessoas irão para outro site.
Em uma solução ideal, o navegador começaria a baixar seus scripts o mais rápido possível, enquanto analisava o restante do documento.
A abordagem moderna
Hoje, os navegadores suportam os atributos async
e defer
nos scripts. Esses atributos informam ao navegador que é seguro continuar analisando enquanto os scripts estão sendo baixados.
assíncrono
<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
Os scripts com o atributo assíncrono são executados de forma assíncrona. Isso significa que o script é executado assim que é baixado, sem bloquear o navegador enquanto isso.
Isso implica que é possível fazer o download e executar o script 2 antes do script 1.
De acordo com http://caniuse.com/#feat=script-async , 97,78% de todos os navegadores suportam isso.
adiar
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
Os scripts com o atributo defer são executados em ordem (ou seja, primeiro script 1, depois script 2). Isso também não bloqueia o navegador.
Diferentemente dos scripts assíncronos, os scripts de adiamento são executados somente após o carregamento do documento inteiro.
De acordo com http://caniuse.com/#feat=script-defer , 97,79% de todos os navegadores suportam isso. 98,06% o apóiam pelo menos parcialmente.
Uma observação importante sobre a compatibilidade do navegador: em algumas circunstâncias, o IE <= 9 pode executar scripts adiados fora de ordem. Se você precisar oferecer suporte a esses navegadores, leia isso primeiro!
Conclusão
O estado da arte atual é colocar scripts na <head>
tag e usar os atributos async
ou defer
. Isso permite que seus scripts sejam baixados o mais rápido possível, sem bloquear o navegador.
O bom é que seu site ainda deve carregar corretamente nos 2% dos navegadores que não suportam esses atributos enquanto acelera os outros 98%.