Etiqueta de script - assíncrona e adiada

548

Eu tenho algumas perguntas sobre os atributos asynce deferpara a <script>tag que, no meu entender, só funciona nos navegadores HTML5.

Um dos meus sites tem dois arquivos JavaScript externos que atualmente ficam logo acima da </body>tag; o primeiro é originário do google e o segundo é um script externo local.

Com relação à velocidade de carregamento do site

  1. Existe alguma vantagem em adicionar asyncaos dois scripts que tenho na parte inferior da página?

  2. Haveria alguma vantagem em adicionar a asyncopção aos dois scripts e colocá-los no topo da página <head>?

  3. Isso significa que eles são baixados à medida que a página é carregada?
  4. Suponho que isso causaria atrasos nos navegadores HTML4, mas aceleraria o carregamento da página nos navegadores HTML5?

Usando <script defer src=...

  1. O carregamento dos dois scripts internos <head>com o atributo deferafetaria o mesmo que os scripts anteriores </body>?
  2. Mais uma vez, presumo que isso atrasaria os navegadores HTML4.

Usando <script async src=...

Se eu tiver dois scripts com asyncativado

  1. Eles baixariam ao mesmo tempo?
  2. Ou um de cada vez com o restante da página?
  3. A ordem dos scripts se torna um problema? Por exemplo, um script depende do outro, portanto, se um for baixado mais rapidamente, o segundo poderá não ser executado corretamente etc.

Por fim, é melhor deixar as coisas como estão até que o HTML5 seja mais comumente usado?

Adão
fonte
5
asyncé novo (ish), mas deferfaz parte do IE desde o IE4. deferfoi adicionado a outros navegadores muito mais recentemente, mas as versões mais antigas desses navegadores tendem a ficar muito menos tempo.
Alohci
3
Agora, o HTML5 se tornou muito popular!
sept08
2
deferé o mesmo que colocar scripts na parte inferior do HTML, o que é comum há muitos anos.
vsync
1
@vsync não necessariamente verdadeiro, o navegador fará o download do JS com a marca deferida quando analisar a marca de script, mas adiará a execução até pouco antes de DOMContentLoaded. O download é sem bloqueio. A colocação na parte inferior do HTML atrasará o download e a execução do JS até que o DOM seja construído, mas você ainda terá um atraso adicional aguardando o download.
Brad Geada
@BradFrost - O download está bloqueando na minha opinião, no sentido em que está consumindo largura de banda da Internet, e para aqueles com conexão lenta, considero imperativo primeiro carregar o documento e só então, quando ele tiver sido renderizado, começar a baixar arquivos javascript . Isto é verdade nos casos em que o conteúdo não é bem-acoplada javascript para renderizar tudo (como SPA )
vsync

Respostas:

406

Mantenha seus scripts logo antes </body>. O Async pode ser usado com scripts localizados em algumas circunstâncias (consulte a discussão abaixo). O adiamento não fará muita diferença para scripts localizados lá, porque o trabalho de análise do DOM já foi praticamente feito de qualquer maneira.

Aqui está um artigo que explica a diferença entre async e adiar: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ .

Seu HTML será exibido mais rapidamente em navegadores mais antigos se você mantiver os scripts no final do corpo imediatamente antes </body>. Portanto, para preservar a velocidade de carregamento em navegadores antigos, você não deseja colocá-los em nenhum outro lugar.

Se o seu segundo script depende do primeiro script (por exemplo, seu segundo script usa o jQuery carregado no primeiro script), você não pode fazê-los assíncronos sem código adicional para controlar a ordem de execução, mas pode adiar porque os scripts adiados ainda será executado em ordem, apenas após a análise do documento. Se você possui esse código e não precisa que os scripts sejam executados imediatamente, você pode fazê-los assíncronos ou adiados.

Você pode colocar os scripts na <head>tag e configurá-los para, defere o carregamento dos scripts será adiado até que o DOM seja analisado e que obtenha uma rápida exibição da página em novos navegadores compatíveis com adiamento, mas não ajudará em nada em navegadores mais antigos e não é realmente mais rápido do que apenas colocar os scripts antes do </body>que funciona em todos os navegadores. Então, você pode ver por que é melhor colocá-los logo antes </body>.

O Async é mais útil quando você realmente não se importa quando o script é carregado e nada mais depende do usuário depende do carregamento do script. O exemplo mais citado para o uso de assíncrono é um script de análise como o Google Analytics, pelo qual você não deseja que nada espere, não é urgente que seja executado em breve e fica sozinho, portanto, nada mais depende disso.

Normalmente, a biblioteca jQuery não é uma boa candidata a assíncrona porque outros scripts dependem dela e você deseja instalar manipuladores de eventos para que sua página comece a responder a eventos do usuário e talvez seja necessário executar algum código de inicialização baseado em jQuery para estabelecer o estado inicial da página. Ele pode ser usado de forma assíncrona, mas outros scripts precisarão ser codificados para não serem executados até que o jQuery seja carregado.

jfriend00
fonte
8
O adiamento deve executá-los em ordem ainda, mas execute antes de dom-contentloaded. Isso não significa que colocá-lo na cabeça seria mais rápido, pois ele pode começar a baixá-los ANTES O html do corpo é analisado?
21413 Kevin
9
Você disse que colocar scripts heade configurá-los defernão será mais rápido do que colocá-los antes </body>, mas, pelo que li, isso está incorreto. Pense nisso - se você inserir os scripts <head>, eles começarão a ser baixados imediatamente, enquanto que se eles estiverem corretos antes </body>, todos os outros elementos serão baixados primeiro.
Nate
12
@ Nate - Não fará o seu documento carregar mais rápido, o que é o meu ponto. Você está certo de que ele pode melhorar o carregamento do script mais cedo, mas também pode diminuir o carregamento do documento e do conteúdo, porque você está usando parte da largura de banda e uma das conexões limitadas que o navegador fará com um determinado servidor para carregue o script enquanto ele também está tentando carregar seu conteúdo.
jfriend00
4
"Se o seu segundo script depende do primeiro script ... então você não pode fazê-lo assíncrono ou adiado" - isso não é verdade, com o adiamento que eles executam em ordem.
usar o seguinte
2
Neste ponto, o requisito </body> não é realmente necessário nos desenvolvimentos do navegador desde 2012, quando esta resposta foi publicada.
Bgcode 12/05/19
844

Esta imagem explica a tag de script normal, assíncrona e adiada

insira a descrição da imagem aqui

  • Os scripts assíncronos são executados assim que o script é carregado, portanto, não garante a ordem de execução (um script que você incluiu no final pode ser executado antes do primeiro arquivo de script)

  • Adiar scripts garante a ordem de execução na qual eles aparecem na página.

Refira este link: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

Prasanth Bendra
fonte
Eu acho que um exemplo com vários scripts teria sido melhor para ilustrar sua seqüência
vsync
4
@writofmandamus Parece que asyncvai ganhar. Veja stackoverflow.com/questions/13821151/…
Monsignor
Obrigado pela boa explicação. No entanto, as imagens não estão em escala. No caso de apenas a <script>tag, o comprimento total do carregamento da página é maior pelo tempo necessário para o download do arquivo de script.
arni
@BhavikHirani De acordo com este site , usar async e adiar na mesma tag de script usa async se o navegador suportar, ou volta a adiar se não suportar async, mas suporta adiamento. Os comportamentos são bem diferentes, então eu não recomendaria o uso de ambos, pois o resultado é imprevisível e pode ser uma ótima fonte de bugs.
Adrian Wiik
@arni Somente se a largura de banda for totalmente utilizada, o que raramente é. E os dois downloads compartilhariam a largura de banda, não o bloco um. - Além disso: essas imagens mostram a análise em verde, não o download.
Robert Siemer em
213

HTML5: async,defer

No HTML5, você pode informar ao navegador quando executar seu código JavaScript. Existem 3 possibilidades:

<script       src="myscript.js"></script>

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

<script defer src="myscript.js"></script>
  1. Sem asyncou defer, o navegador executará seu script imediatamente, antes de renderizar os elementos abaixo da sua tag de script.

  2. Com async(assíncrono), o navegador continuará carregando a página HTML e renderizando-a enquanto o navegador carrega e executa o script ao mesmo tempo.

  3. Com defer, o navegador executará seu script quando a página terminar de analisar. (não é necessário concluir o download de todos os arquivos de imagem. Isso é bom.)

Dinesh
fonte
é necessário o modelo do blogger.com async=""antes de validar e salvar as alterações do modelo.
Noobninja 12/09/2015
1
Nota: não há garantia de que os scripts serão executados na ordem em que são especificados usando o Async. "Portanto, se o seu segundo script depende do primeiro script, evite o Async."
Faisal Naseer
2
async- Os scripts são executados no momento em que foram baixados, sem considerar sua ordem no arquivo HTML.
vsync
30

Os scripts asynce os defercomeçam a baixar imediatamente sem pausar o analisador e ambos oferecem suporte a um onloadmanipulador opcional para atender à necessidade comum de executar a inicialização que depende do script.

A diferença entre asynce defergira em torno de quando o script é executado. Cada asyncscript é executado na primeira oportunidade após o término do download e antes do evento de carregamento da janela. Isso significa que é possível (e provável) que os asyncscripts não sejam executados na ordem em que ocorrem na página. Enquanto os deferscripts, por outro lado, são garantidos para serem executados na ordem em que ocorrem na página. Essa execução inicia após a conclusão da análise, mas antes do DOMContentLoadedevento do documento .

Fonte e mais detalhes: aqui .

Zameer Khan
fonte
25

Enfrentou o mesmo tipo de problema e agora entendeu claramente como ambos funcionarão. Espero que este link de referência seja útil ...

Assíncrono

Quando você adiciona o atributo assíncrono à sua tag de script, o seguinte acontece.

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Faça solicitações paralelas para buscar os arquivos.
  2. Continue analisando o documento como se nunca tivesse sido interrompido.
  3. Execute os scripts individuais no momento em que os arquivos são baixados.

Adiar

O adiamento é muito semelhante ao assíncrono, com uma grande diferença. Aqui está o que acontece quando um navegador encontra um script com o atributo defer.

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Faça solicitações paralelas para buscar os arquivos individuais.
  2. Continue analisando o documento como se nunca tivesse sido interrompido.
  3. Conclua a análise do documento, mesmo que os arquivos de script tenham sido baixados.
  4. Execute cada script na ordem em que foram encontrados no documento.

Referência: Diferença entre Async e Adiar

kamesh
fonte
7

asynce deferfará o download do arquivo durante a análise de HTML. Ambos não interromperão o analisador.

  • O script com asyncatributo será executado assim que for baixado. Enquanto o script com deferatributo será executado após a conclusão da análise do DOM.

  • Os scripts carregados asyncnão garantem nenhum pedido. Enquanto os scripts carregados com o deferatributo mantêm a ordem em que aparecem no DOM.

Use <script async>quando o script não depende de nada. quando o script depende do uso.

A melhor solução seria adicionar a parte inferior do corpo. Não haverá problemas com o bloqueio ou a renderização.

NavyaKumar
fonte
Só quero esclarecer aqui, duas coisas estão acontecendo aqui 1. Download do recurso 2. Execução do recurso. O download de recursos nos dois casos (assíncrono e adiado) não está bloqueando, significa que eles não bloqueiam a análise de html, enquanto a execução em assíncrona bloqueia a análise e, no caso de adiamento, a execução ocorre após a análise da marcação html, portanto, sem bloqueio neste caso.
pOoOf
5

Acho que Jake Archibald nos apresentou algumas idéias em 2013 que podem adicionar ainda mais positividade ao tópico:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

O Santo Graal está fazendo o download de um conjunto de scripts imediatamente, sem bloquear a renderização e executar o mais rápido possível, na ordem em que foram adicionados. Infelizmente, o HTML o odeia e não o deixa fazer isso.

(...)

A resposta está na especificação HTML5, embora oculta na parte inferior da seção de carregamento de scripts. " O atributo IDL assíncrono controla se o elemento será executado de forma assíncrona ou não. Se o sinalizador" force-async "do elemento estiver definido, ao obter, o atributo IDL assíncrono deve retornar true e, ao definir, o" force-async " A bandeira deve primeiro estar desabilitada… ".

(...)

Os scripts criados e adicionados dinamicamente ao documento são assíncronos por padrão ; eles não bloqueiam a renderização e são executados assim que são baixados, o que significa que podem sair na ordem errada. No entanto, podemos marcá-los explicitamente como não assíncronos:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

Isso fornece aos nossos scripts uma mistura de comportamentos que não podem ser alcançados com HTML simples. Por não serem explicitamente assíncronos, os scripts são adicionados a uma fila de execução, a mesma fila a que foram adicionados em nosso primeiro exemplo de HTML simples. No entanto, ao serem criados dinamicamente, eles são executados fora da análise de documentos, para que a renderização não seja bloqueada durante o download (não confunda o carregamento de scripts não assíncronos com a sincronização XHR, o que nunca é uma coisa boa).

O script acima deve ser incluído embutido no cabeçalho das páginas, fazendo o download de scripts na fila o mais rápido possível, sem interromper a renderização progressiva, e é executado o mais rápido possível na ordem especificada. O download do "2.js" é gratuito antes do "1.js", mas não será executado até que o "1.js" tenha sido baixado e executado com êxito, ou falhe. Viva! download assíncrono, mas execução ordenada !

Ainda assim, essa pode não ser a maneira mais rápida de carregar scripts:

(...) Com o exemplo acima, o navegador precisa analisar e executar scripts para descobrir quais scripts baixar. Isso oculta seus scripts dos scanners de pré-carregamento. Os navegadores usam esses scanners para descobrir recursos nas páginas que provavelmente visitará em seguida ou descobrir os recursos da página enquanto o analisador é bloqueado por outro recurso.

Podemos adicionar a descoberta novamente colocando isso na cabeça do documento:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

Isso indica ao navegador que a página precisa de 1.js e 2.js. link [rel = subresource] é semelhante ao link [rel = pré-busca], ​​mas com semânticas diferentes. Infelizmente, atualmente, ele é suportado apenas no Chrome, e você deve declarar quais scripts carregar duas vezes, uma vez por meio de elementos de link e novamente em seu script.

Correção: originalmente, afirmei que eles foram coletados pelo scanner de pré-carregamento, não são, pelo analisador comum. No entanto, o scanner de pré-carregamento pode buscá-las, mas ainda não o faz, enquanto os scripts incluídos no código executável nunca podem ser pré-carregados. Agradeço a Yoav Weiss, que me corrigiu nos comentários.

mjfneto
fonte
1

Parece que o comportamento de adiar e assíncrono depende do navegador, pelo menos na fase de execução. NOTA: o adiamento se aplica apenas a scripts externos. Estou assumindo que async segue o mesmo padrão.

No IE 11 e abaixo, a ordem parece ser assim:

  • assíncrono (pode ser parcialmente executado durante o carregamento da página)
  • nenhum (pode ser executado durante o carregamento da página)
  • adiar (é executado após a página ser carregada, todos adiados em ordem de posicionamento no arquivo)

No Edge, Webkit, etc., o atributo async parece ser ignorado ou colocado no final:

  • data-pagespeed-no-adiar (executa antes de qualquer outro script, enquanto a página está sendo carregada)
  • nenhum (pode ser executado enquanto a página está carregando)
  • adiar (espera até que o DOM seja carregado, todos adiam em ordem de posicionamento no arquivo)
  • assíncrono (parece aguardar até que o DOM seja carregado)

Nos navegadores mais recentes, o atributo data-pagespeed-no-defer é executado antes de qualquer outro script externo. Isto é para scripts que não dependem do DOM.

NOTA: Use adiar quando precisar de uma ordem explícita de execução de seus scripts externos. Isso informa ao navegador para executar todos os scripts adiados em ordem de posicionamento no arquivo.

AO LADO: O tamanho dos javascripts externos importava ao carregar ... mas não tinha efeito na ordem de execução.

Se você está preocupado com o desempenho de seus scripts, convém considerar a minificação ou simplesmente carregá-los dinamicamente com um XMLHttpRequest.

Charles Owen
fonte
data-pagespeed-no-deferé um atributo usado pelo módulo PageSpeed do servidor . O atributo por si próprio não tem efeito em nenhum navegador. data-pagespeed-no-defer
Qtax 20/04