Defer e Async – Carregamento de arquivos JavaScript

Salve galera, hoje quero abordar sobre otimização de websites, vou abordar duas tags do HTML5 que podem diminuir bem o gargalo do tempo de carregamento dos arquivos de JavaScript, da qual já fiz uma introdução em outro tópico, Alto Desempenho com JavaScript da qual sabemos que um dos principais impasses para tratar o carregamento do nosso website é a chamada correta para os arquivos JavaScript, seja um arquivo externo ou mesmo uma chamada interna, sempre devemos nos atentar sobre isto.

Carregamento do Site

Sabemos que os browser embora evoluíram consideravelmente nessa última década, ainda não há um padrão exato de como ele renderiza todos os nossos arquivos e como ele vai se comportar a cada requisição do usuário, quando se trata de eventos com JavaScript ele trabalha em uma “camada” do browser da qual ele pode escrever, modificar, excluir e inserir elementos no website por isso ele impacta tanto no carregamento do site.

Craig Bucker disse – “Para o usuário pode ser indiferente um segundo ou dois de tempo de resposta de uma requisição, não é perceptível do ponto de vista humano esse “leg” pois o conteúdo principal está sendo exibido. Mesmo que essa solução é inadequada para aplicações client-side ou multi-megabyte. Em casos extremos, é necessário carregar bibliotecas de código grandes usando injeções, tag´s script ou técnicas Ajax, isso evitaria o bloqueio, mas requer um código adicional e testes rigorosos para garantir que os scripts são executados na ordem correta em todos os navegadores.”

O atributo defer

O atributo defer garante ao navegador, que em relação aos arquivos JavaScript que serão executados em seu browser não existe nenhuma tag document.write ou DOM que irá ser executado no instante de “load” do seu site, abaixo está um exemplo de como devemos atribuir em nossos script para fazer referencia que iremos utiliza-lo:

<script src="file.js" defer></script>

Quando você utiliza a tag defer os browser entendem que você irá baixar outros arquivos js em paralelo, isso irá fazer com que todos os arquivos do seu site carreguem no mesmo instante.  Isso evitaria o interrompimento do carregamento do seu site por conta de algum arquivo externo javascript , lembrando que não há um estudo minucioso para isso para utilizarmos essa tag para mobile já que sabemos por default que o jQuery é deveras grande para ser carregado e a cada requisição que o usuario fez ele baixa o arquivo novamente tornando seu site lento, por isso devo ressaltar não utilize jQuery para mobile.

Abaixo estou colocando para quais browser o atributo defer funciona:

Browser que aceitam a tag defer

Browser que aceitam a tag defer

O atributo async

O atributo async foi introduzido junto com o HTML5, ele possui o mesmo funcionamento que o defer as mesmas caracteristicas, carregar arquivos paralelamente porem seu funcionamento não é muito prático ele possui uma exceção, ele não garante que os arquivos serão executados em sequências mas eles serão carregados no instante do “onload” dos arquivos.

<script src="file.js" async></script>

Browser que suportam o async

Browser que suportam o async

De maneira geral para sabermos como fica o carregamentos dos arquivos JavaScript utilizando as tags, defer, async e sem elas.

Defer vs Async vs Normal

Defer vs Async vs Normal

Execução sem as tags:(Normal)

Por default sem o uso dessas tags o browser irá fazer o carregamento dos arquivos js, porém no mento que estiver executando o html ele vai ser interrompido para chamar esses arquivos somente depois de finalizado que ele finaliza a renderização do template para o usuário.

Execução com as tags:(defer)

Resumindo ele vai atrasar a execução do arquivos js até que finalize a renderização por completo do HTML, a parte positiva disto é que mesmo ele tendo esse comportamento ele vai deixar o DOM disponivel.

Execução com as tags:(async)

Se você não se importa quando o seus arquivos scripts estarão disponiveis para o usuario acessar, então utilize essa tag sem
preocupação, ele vai deixar renderizar seu template por completo e depois vai carregar os arquivos js de forma assíncrona.

Referencias:
http://www.sitepoint.com/non-blocking-async-defer/
http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/

Alto Desempenho – Inclusão do Código JavaScript

E ae, galera blz? Chegando aqui para falar de mais um tópico abordando JavaScript, conforme discutido nas colunas anteriores, estou focando mais isso, este mês de julho fiz algumas aquisições para minha biblioteca particular:

Alto Desempenho JavaScript

– JavaScript o Guia Definitivo

– O Melhor do JavaScript

– Padrões JavaScript

– JavaScript de Alto Desempenho

Estarei aos poucos trazendo aqui no blog os capítulos que achar mais pertinente, blz!?

Deu para aproveitar a agenda de julho e conciliar um curso de férias sobre Programação Avançada com JavaScript pela Caelum deu para dar um upgrade “considerado” nos conceitos sobre JavaScript,  estarei postando em breve algumas dicas que peguei de lá com o instrutor e dando um feedback para quem pretende fazer curso na Caelum da parte de frontend.

Antecipando o review, recomendo para quem procura um curso que engloba essas duas tecnologias(JavaScript e Jquery), o material e o instrutor são bons, a didática dele é excelente, bem prático os exercícios, contexto real não fica fazendo execícios tolos de somar, dividir e onClick, a maioria das escolas que dizem dar curso de JavaScript fazem isso, então atente-se sobre a grade do curso, o que considero de suma importância em todo curso de JavaScript(DOM, BOM, Function, Prototype, Classe e Herança) outra coisa que pude perceber e sobre a curva de aprendizado é bem acentuada. \o/

Bom chega de firulas, vamos falar do que importa, como dito no inicio do tópico quero abordar com vocês um tópico que vi no livro Alto Desempenho – JavaScript do Nicholas C. Zakas.

Primeiro tópico que já engloba o livro na parte de desempenho e que gera muita discussão pela comunidade é aonde deixar as tags <script>? Entre as tags <head>? Ou seria entre as tags <body>?!

A importância da chamada dos script na sua página, deve ser muito bem analisada e estruturada pois isso pode impactar tanto no carregamento da página quanto no desempenho da mesma.

Antigamente, todos partiam do principio que o correto seria:

Jeito Errado: Carregamento de todos os arquivos JS no inicio entre as tags <HEAD> da página pode afetar o desempenho de carregamento da sua página pois o interpretador como lê toda a chamada da página “linearmente” so vai mostrar o conteudo que está entre as tags <BODY>, após carregar todos os seus arquivos javascript, pense agora no usuario com uma conexão mais lenta tentando acessar seu site e aparece uma página branca, entendeu? Isso sem levar em consideração que antigamente não havia um estudo minucioso sobre os browser quanto ao tratamento do carregamento desses arquivos, o que por sua vez faz compreender um dos problemas em se trabalhar com javascript.

<!DOCTYPE html>
<html> 
<head> 
<title>Carregamento JavaScript – Jeito Errado</title> 
<script src="http://teste1/scripts/lib/prototype.js"></script>
<script src="http://teste1/scripts/lib/scriptaculous.js"></script>
<script src=”http://teste1/global/scripts/browserdetect.js”></script&gt;
<script src=”http://teste1/global/scripts/apple_core.js”></script&gt;
<script src=”http://teste1/scripts/search_decorator.js”></script&gt;
<script src=”http://teste1/scripts/promomanager.js”></script&gt;
<script src=”http://images.apple.com/home/scripts/ticker.js”></script&gt;
<script src=”http://images.apple.com/home/scripts/promotracker.js”></script&gt;
</head> 
<body> 
<h1>Texto</h1> 
</body> 
</html>

Jeito Certo: Carregamento de todos os arquivos JS no final da página antes do fechamento da tag <BODY>, isso proporciona o carregamento do seu site por completo depois que seu site foi carregado, o browser faz o tratamento para fazer a chamada para todos os arquivos externos do JavaScript, irei abordar depois sobre como os browser funcionam no carregamento de arquivos para modelo Serial e modelo Paralelo , suma importância entender esses conceitos!

<!DOCTYPE html>
<html>
<head>
<title>Carregamento JavaScript - Jeito Certo</title>
</head>
<body>
<h1>Texto</h1>
<script src=”http://images.apple.com/global/scripts/lib/prototype.js”></script&gt;
<script src=”http://images.apple.com/global/scripts/lib/scriptaculous.js”></script&gt;
<script src=”http://images.apple.com/global/scripts/browserdetect.js”></script&gt;
<script src=”http://images.apple.com/global/scripts/apple_core.js”></script&gt;
<script src=”http://images.apple.com/global/scripts/search_decorator.js”></script&gt;
<script src=”http://images.apple.com/global/scripts/promomanager.js”></script&gt;
<script src=”http://images.apple.com/home/scripts/ticker.js”></script&gt;
<script src=”http://images.apple.com/home/scripts/promotracker.js”></script&gt;
</body>
</html>

A internet evoluiu bastante nesses últimos 15 anos, juntamente com os browsers ainda mais depois que a Google lançou o Chrome, digamos que através disso está ocorrendo um “padrão” de como os sites devem ser carregados, entretanto ainda há muito a ser melhorado pois dependendo da tecnologia que você está utilizando seu site pode ser interpretado de maneira diferente em cada browser, entramos em outro tópico que seria Cross-Browser.

Uma abordagem interessante que o Nicholas Zakas @slicknetcoloca em seu livro é que quando eles perceberam no Yahoo o problema do fluxo de carregamento dos arquivos e o tempo de resposta para o usuario ao requisitar uma página, adotando essa abordagem de inserir as tags <script> antes do fechamento da tag body, ao invés de fazer essa chamada como no exemplo abaixo:

Modelo 1:  Chamando todos os scripts
<script src="http://images.apple.com/global/scripts/browserdetect.js"></script> <script src="http://images.apple.com/global/scripts/apple_core.js"></script> <script src="http://images.apple.com/global/scripts/search_decorator.js"></script>

Modelo 2: Chamando todos os scripts de maneira resumida.

<script src="http://images.apple.com/global/scripts/browserdetect.js"& "http://images.apple.com/global/scripts/apple_core.js" & "http://images.apple.com/global/scripts/search_decorator.js" />

Abordando de forma rápida como os navegadores faziam para executar os arquivos js no momento da leitura.

Modelo Paralelo e Modelo Serial

Modelo Serial: Ele realiza o carregamento do seu script na tag head, ele executava arquivos de forma isolada, executava o primeiro enquanto ele não finalizava ele não seguia para o próximo, agora pense se um desses arquivos estiver corrompido como iria ficar seu site? Abaixo está um pequeno desenho explicando o acesso de vários arquivos js.

Modelo Paralelo: Ele consegue carregar todos os arquivos ao mesmo tempo de forma independente não importando seu tamanho e não sendo necessário aguardar finalizar um para iniciar outro, com isso seu site estará mais rápido na requisição do cliente e não haverá quebras.

Carregando arquivos em Modo Paralelo

Carregando arquivos em Modo Paralelo

Lógico que para fazer esse recurso você pode utilizar uma biblioteca do javascript que chama head.js ela faz esse recurso de carregar todos os arquivos ao mesmo tempo ou então utilizar uma tag do HTML 5 que chama defer, bom em suma ficaria assim a chamada de seus arquivos com esse recurso.

Defer – Garante dependência ou seja para carregar um arquivo ele depende do outro, ou seja ele não termina seu carregamento enquanto não executar todos os arquivos que seu site depende, existe também outra tag do HTML5 que chama assync porém ele não garante essa dependência ou seja se você utilizar ele pode executar um arquivo e o outro não carregou por completo e ele não compreende isso e da status finalizado para o script que não finalizou.

Se você for escolher essas tags do HTML5 para trabalhar no Internet Explorer , devo ressaltar que há um conflito pois o browser da Microsoft ainda não está padronizado aceitando essas tags, como para tudo tem um jeito então pesquisando você pode utilizar como solução para o IE, o ScriptLoader ou então comentado acima head.js.

Mais informações:

https://developers.google.com/speed/articles/html5-performance?hl=pt-BR
http://headjs.com/
http://labjs.com/
http://novatec.com.br/livros/javascriptdesemp/capitulo9788575222416.pdf