16 métodos para adiar ou agendar JavaScript

Aprenda como adiar e agendar JavaScript

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-24

Por que adiar ou agendar o JavaScript?

O JavaScript pode (e irá) desacelerar o seu site de várias maneiras. Isso pode ter todos os tipos de impacto negativo nos Core Web Vitals. O JavaScript pode competir por recursos de rede, pode competir por recursos de CPU (bloquear a thread principal) e pode até bloquear a análise de uma página web. Adiar e agendar seus scripts pode melhorar drasticamente os Core Web Vitals.

Última revisão por Arjen Karel em fevereiro de 2026

Para minimizar os efeitos desagradáveis que o JavaScript pode ter nos Core Web Vitals, geralmente é uma boa ideia especificar quando um script entra na fila para download e agendar quando ele pode ocupar tempo de CPU e bloquear a thread principal.

Como o tempo do JavaScript pode afetar os Core Web Vitals?

Como o tempo do JavaScript pode afetar os Core Web Vitals? Basta dar uma olhada neste exemplo da vida real. A primeira página é carregada com JavaScript 'render blocking'.  As métricas de paint, bem como o Total Blocking Time, são muito ruins. O segundo exemplo é exatamente da mesma página, mas com o JavaScript adiado. Você verá que a imagem do LCP ainda sofreu um grande impacto. O terceiro exemplo tem o mesmo script executado após o 'load event' da página e tem as chamadas de função divididas em partes menores. Este último está passando nos Core Web Vitals com folga.

null
null
null


Por padrão, o JavaScript externo no head da página bloqueará a criação da render tree. Mais especificamente: quando o navegador encontra um script no documento, ele deve pausar a construção do DOM, passar o controle para o runtime do JavaScript e deixar o script executar antes de prosseguir com a construção do DOM. Isso afetará suas métricas de Paint (Largest Contentful Paint e First Contentful Paint).

JavaScript adiado ou async ainda pode impactar as métricas de paint, especialmente o Largest Contentful Paint porque ele será executado, e bloqueará a thread principal, assim que o DOM for criado (e elementos comuns de LCP, como imagens, podem não ter sido baixados).

Arquivos JavaScript externos também irão competir por recursos de rede. Arquivos JavaScript externos geralmente são baixados antes das imagens. Se você estiver baixando muitos scripts, o download de suas imagens será atrasado.

Por último, mas não menos importante, o JavaScript pode bloquear ou atrasar a interação do usuário. Quando um script está usando recursos de CPU (bloqueando a thread principal), um navegador não responderá a entradas (cliques, rolagem, etc.) até que esse script seja concluído. Isso afeta diretamente sua pontuação de Interaction to Next Paint (INP).

O impacto é mensurável. De acordo com o Web Almanac de 2025, apenas 15% das páginas mobile passam na auditoria de render-blocking resources. A mediana do Total Blocking Time mobile é de 1.916 milissegundos. Isso representa quase 2 segundos completos em que o navegador não consegue responder à entrada do usuário. Escolher o método de adiamento correto para cada script é como você reduz esse número.

Como agendar ou adiar o JavaScript corrige os Core Web Vitals?

Agendar ou adiar o JavaScript não corrige os Core Web Vitals por si só. É tudo uma questão de usar a ferramenta certa para a situação certa. Como regra, você deve tentar atrasar seus scripts o mínimo possível, mas colocá-los na fila para download e executá-los no momento apropriado.

Como escolher o método de adiamento correto?

Nem todos os scripts são iguais e cada script tem sua própria funcionalidade. Alguns scripts são importantes para ter no início do processo de renderização, outros não.

null

Eu gosto de categorizar os JavaScripts em 4 grupos baseados em seu nível de importância.

1. Render critical. Estes são os scripts que mudarão a aparência de uma página web. Se eles não carregarem, a página não parecerá completa. Estes scripts devem ser evitados a todo custo. Se você não puder evitá-los por algum motivo, eles não devem ser adiados. Por exemplo, um slider superior ou um script de teste A/B.
2. Critical. Estes scripts não mudarão a aparência de uma página web (muito), mas a página não funcionará bem sem eles. Estes scripts devem ser adiados (deferred) ou assíncronos (asynced). Por exemplo, os scripts do seu menu.
3. Important. Estes são scripts que você deseja carregar porque são valiosos para você ou para o visitante. Eu costumo carregar esses scripts após o load event ter sido disparado. Por exemplo, analytics ou um botão 'voltar ao topo'.
4. Nice to have. Estes são scripts que você pode viver sem, se for absolutamente necessário. Eu carrego esses scripts com a prioridade mais baixa e os executo apenas quando o navegador está ocioso. Por exemplo, um widget de chat ou um botão do facebook.

Método 1: Usar o atributo defer

Scripts com o atributo defer farão download em paralelo e serão adicionados à fila de JavaScript defer. Logo antes do navegador disparar o evento DOMContentLoaded, todos os scripts nessa fila serão executados na ordem em que aparecem no documento.

<script defer src='javascript.js'></script>

O 'truque do defer' geralmente corrige muitos problemas, especialmente as métricas de paint. Infelizmente não há garantia, depende da qualidade dos scripts. Scripts adiados serão executados assim que todos os scripts tiverem sido carregados e o HTML for analisado (DOMContentLoaded). O elemento de LCP (geralmente uma imagem grande) pode não estar carregado até então e os scripts adiados ainda causarão um atraso no LCP.

Quando usar:

Use scripts adiados para scripts Críticos que são necessários o mais rápido possível.

Vantagens:

  1. Scripts adiados farão download em paralelo
  2. O DOM estará disponível no momento da execução

Desvantagens:

  1. Scripts adiados podem atrasar suas métricas de LCP 
  2. Scripts adiados bloquearão a thread principal assim que forem executados
  3. Pode não ser seguro adiar scripts quando scripts inline ou async dependem deles

Método 2: Usar o atributo async

Scripts com o atributo async farão download em paralelo e serão executados imediatamente após terem terminado o download.

<script async src='javascript.js'></script>

Scripts async farão pouco para corrigir seus problemas de velocidade de página. É ótimo que eles sejam baixados em paralelo, mas é apenas isso. Uma vez baixados, eles bloquearão a thread principal enquanto são executados.

Quando usar:

Use scripts async para scripts Críticos que são necessários o mais rápido possível e são autônomos (não dependem de outros scripts).

Vantagens:

  1. Scripts async farão download em paralelo.
  2. Scripts async serão executados o mais rápido possível.

Desvantagens:

  1. DOMContentLoaded pode acontecer tanto antes quanto depois do async.
  2. A ordem de execução dos scripts será desconhecida de antemão.
  3. Você não pode usar scripts async que dependem de outros scripts async ou deferred

Para uma comparação detalhada dessas duas abordagens, veja defer vs async e como isso afeta os Core Web Vitals.

Método 3: Usar módulos

Scripts modulares são adiados por padrão, a menos que tenham o atributo async. Nesse caso, eles serão tratados como scripts async

<script module src='javascript.js'></script>

Módulos são uma nova maneira de pensar sobre JavaScript e corrigem algumas falhas de design. Fora isso, usar módulos de script não acelerará o seu site. 

Quando usar:

Quando sua aplicação é construída de forma modular, faz sentido também usar módulos JavaScript.

Vantagens:

  1. Módulos são adiados por padrão
  2. Módulos são mais fáceis de manter e funcionam muito bem com web design modular
  3. Módulos permitem fácil divisão de código com importações dinâmicas, onde você importa apenas os módulos de que precisa em um determinado momento.

Desvantagens:

  1. Módulos por si só não melhorarão os Core Web Vitals
  2. Importar módulos just-in-time ou de forma dinâmica pode ser lento e piorar o INP 

Método 4: Colocar os scripts perto do final da página

Scripts no rodapé são colocados na fila para download em um momento posterior. Isso priorizará outros recursos que estão no documento acima da tag de script.

<html>
   <head></head>
   <body>
      [your page contents here]
      <script defer src='javascript.js'></script>
   </body>
</html>

Colocar seus scripts na parte inferior da página é uma técnica interessante. Isso irá agendar outros recursos (como imagens) antes dos seus scripts. Isso aumentará a chance de que eles estejam disponíveis para o navegador e pintados na tela antes que os arquivos JavaScript terminem o download e a thread principal seja bloqueada pela execução do script. Ainda assim... sem garantia.

Quando usar:

Quando seus scripts já estão com um desempenho muito bom, mas você deseja priorizar levemente outros recursos, como imagens e webfonts.

Vantagens:

  1. Colocar scripts na parte inferior da página não requer muito conhecimento.
  2. Se feito corretamente, não há risco de que isso quebre sua página

Desvantagens:

  1. Scripts críticos podem ser baixados e executados mais tarde
  2. Isso não corrige nenhum problema subjacente do JavaScript

Método 5: Injetar scripts

Scripts injetados são tratados como scripts async. Eles são baixados em paralelo e são executados imediatamente após o download.

<script>
    const loadScript = (scriptSource) => {
        const script = document.createElement('script');
        script.src = scriptSource;
        document.head.appendChild(script);
    }

    // call the loadscript function that injects 'javascript.js'
    loadScript('javascript.js');
</script>

De uma perspectiva de Core Web Vitals, esta técnica é exatamente a mesma que usar <script async>.

Quando usar:

Este método é frequentemente usado por scripts de terceiros que são acionados o mais cedo possível. A chamada de função torna fácil encapsular e comprimir o código.

Vantagens:

  1. Código contido, que injeta um script async.

Desvantagens:

  1. DOMContentLoaded pode acontecer tanto antes quanto depois do script ser carregado.
  2. A ordem de execução dos scripts será desconhecida de antemão.
  3. Você não pode usar isso em scripts que dependem de outros scripts async ou deferred

Método 6: Injetar scripts em um momento posterior

Scripts nice-to-have, na minha opinião, nunca devem ser carregados como deferred. Eles devem ser injetados no momento mais oportuno. No exemplo abaixo, o script executará após o navegador enviar o evento 'load'.

<script>
window.addEventListener('load', function () {
  // see method 5 for the loadscript function
  loadScript('javascript.js');
});
</script>

Esta é a primeira técnica que irá melhorar de forma confiável o Largest Contentful Paint. Todos os recursos importantes, incluindo imagens, serão baixados quando o navegador disparar o 'load event'. Isso pode introduzir todos os tipos de problemas, porque pode levar muito tempo para o evento load ser chamado.

Quando usar:

Para scripts nice-to-have que não têm motivo para impactar as métricas de paint.

Vantagens:

  1. Não competirá por recursos críticos porque irá injetar o script assim que a página e seus recursos forem carregados

Desvantagens:

  1. Se a sua página for mal projetada em termos de Core Web Vitals, pode levar muito tempo para a página enviar o evento 'load'
  2. Você precisa ter cuidado para não aplicar isso a scripts críticos (como lazy loading, menu etc.)

Método 7: Alterar o tipo do script (e depois alterá-lo de volta)

Se uma tag de script for encontrada em algum lugar da página que 1. tenha um atributo type e 2. o atributo type não seja "text/javascript", o script não será baixado e executado por um navegador. Muitos Loaders de JavaScript (como o RocketLoader da CloudFlare) confiam nesse princípio. A ideia é bem simples e elegante.

Primeiro, todos os scripts são reescritos assim:

<script type="some-cool-script-type" src="javascript.js"></script>

Então, em algum ponto durante o processo de carregamento, esses scripts são convertidos de volta para 'javascripts normais'.

Quando usar:

Este não é um método que eu recomendaria. Corrigir o impacto do JavaScript levará muito mais do que apenas mover cada script um pouco mais para baixo na fila. Por outro lado, se você tem pouco controle sobre os scripts em execução na página ou tem conhecimento insuficiente de JavaScript, esta pode ser sua melhor aposta.

Vantagens:

  1. É fácil, basta habilitar o rocket loader ou outro plugin e todos os seus scripts agora são executados em um momento um pouco posterior.
  2. Provavelmente corrigirá suas métricas de paint, desde que você não use lazy loading baseado em JS.
  3. Funcionará para scripts inline e externos.

Desvantagens:

  1. Você não terá controle granular sobre quando os scripts são executados
  2. Scripts mal escritos podem quebrar
  3. Usa JavaScript para corrigir JavaScript
  4. Não faz nada para corrigir scripts de longa duração

Método 8: Usar o intersection observer

Com o intersection observer, você pode executar uma função (que neste caso carrega um JavaScript externo) quando um elemento rola para a viewport visível.

<script>
const handleIntersection = (entries, observer) => {
    if (entries?.[0].isIntersecting) {
        // load your script or execute another
           function like trigger a lazy loaded element
        loadScript('javascript.js');

        // remove the observer
        observer.unobserve(entries?.[0].target);
    }
};
const Observer = new window.IntersectionObserver()
Observer.observe(document.querySelector('footer'));
</script>

Este é, de longe, o método mais eficaz de adiar JavaScript que existe. Carregue apenas os scripts de que você precisa, logo antes de precisar deles. Infelizmente, a vida real quase nunca é tão limpa e não muitos scripts podem ser vinculados a um elemento que rola para dentro da visualização.

Quando usar:

Use esta técnica o máximo possível! Sempre que um script interage apenas com um componente fora da tela (como um mapa, um slider, um formulário), esta é a melhor maneira de injetar esse script.

Vantagens:

  1. Não interferirá com LCP e FCP dos Core Web Vitals
  2. Nunca injetará scripts que não são usados. Isso irá melhorar o INP

Desvantagens:

  1. Não deve ser usado com componentes que podem estar na viewport visível
  2. É mais difícil de manter do que um <script src="..."> básico
  3. Pode introduzir um layout shift

Método 9: Usar readystatechange

document.readystate pode ser usado como uma alternativa ao evento 'DOMContentloaded' e 'load'. O readystate 'interactive' é geralmente um bom lugar para chamar scripts críticos que precisam alterar o DOM ou adicionar manipuladores de eventos. 
O ready state 'complete' é um bom lugar para chamar scripts que são menos críticos.

document.addEventListener('readystatechange', (event) => {
  if (event.target.readyState === 'interactive') {
    initLoader();
  } else if (event.target.readyState === 'complete') {
    initApp();
  }
});

Método 10: Usar setTimeout sem timeout

setTimeout é um método malvisto, porém muito subestimado, na comunidade de pagespeed. O setTimeout ganhou uma má reputação porque muitas vezes é mal utilizado.  Muitos desenvolvedores acreditam que o setTimeout só pode ser usado para atrasar a execução do script pela quantidade definida de milissegundos. Embora isso seja verdade, o setTimeout na verdade faz algo muito mais interessante. Ele cria uma nova tarefa no final do event loop do navegador. Esse comportamento pode ser usado para agendar suas tarefas de forma eficaz. Também pode ser usado para dividir tarefas longas em tarefas menores separadas

<script>
   setTimeout(() => {
       // load a script or execute another function
       console.log('- I am called from a 0ms timeOut()')
    }, 0);

   console.log('- I was last in line but executed first')
/* Output: - I was last in line but executed first - I am called from a 0ms timeOut() */ </script>

Quando usar:

O setTimeout cria uma nova tarefa no event loop do navegador. Use isso quando sua thread principal estiver sendo bloqueada por muitas chamadas de função que são executadas sequencialmente.

Vantagens:

  1. Pode dividir o código de longa duração em pedaços menores.

Desvantagens:

  1. O setTimeout é um método bastante rudimentar e não oferece priorização para scripts importantes.
  2. Adicionará o código a ser executado no final do loop

Método 11: Usar setTimeout com um timeout

As coisas ficam ainda mais interessantes quando chamamos o setTimeout com um timeout maior que 0ms

<script>
   setTimeout(() => {
       // load a script or execute another function
       console.log('- I am called from a 10ms timeOut()')
    }, 10);

   setTimeout(() => {
       // load a script or execute another function
       console.log('- I am called from a 0ms timeOut()')
    }, 0);

   console.log('- I was last in line but executed first')
/* Output: - I was last in line but executed first - I am called from a 0ms timeOut() - I am called from a 10ms timeOut() */ </script>

Quando usar:

Quando você precisa de um método fácil para agendar um script após o outro, um pequeno timeout resolverá o problema

Vantagens:

  1. Suportado em todos os navegadores

Desvantagens:

  1. Não oferece agendamento avançado

Método 12: Usar uma promise para definir uma microtask

Criar uma microtask também é uma maneira interessante de agendar o JavaScript. Microtasks são agendadas para execução imediatamente após a conclusão do loop de execução atual.

<script>
   const myPromise = new Promise((resolve, reject) => {
      resolve();
   }).then(
      () => {
         console.log('- I was scheduled after a promise')
         }
   );
console.log('- I was last in line but executed first') /* Output: - I was last in line but executed first - I was scheduled after a promise */ </script>

Quando usar:

Quando uma tarefa precisa ser agendada imediatamente após outra tarefa. 

Vantagens:

  1. A microtask será agendada imediatamente após a tarefa terminar de ser executada.
  2. Uma microtask pode ser usada para atrasar partes menos importantes do código JavaScript no mesmo evento. 

Desvantagens:

  1. Não dividirá a thread principal em partes menores. O navegador não terá chance de responder à entrada do usuário.
  2. Você provavelmente nunca precisará usar microtasks para melhorar os Core Web Vitals, a menos que você já saiba exatamente o que está fazendo.

Método 13: Usar uma microtask

O mesmo resultado pode ser alcançado usando queueMicrotask(). A vantagem de usar queueMicrotask() em relação a uma promise é que é um pouco mais rápido e você não precisa lidar com suas promises.

<script>
   queueMicrotask(() => {
      console.log('- I am a microtask')
   })

   console.log('- I was last in line but executed first')

   /*
      Output:
      - I was last in line but executed first
      - I am a microtask
   */
</script>


Método 14: Usar requestIdleCallback

O método window.requestIdleCallback() enfileira uma função para ser chamada durante os períodos ociosos de um navegador. Isso permite que os desenvolvedores realizem trabalhos em segundo plano e de baixa prioridade no event loop principal, sem impactar eventos críticos de latência, como animação e resposta a entradas. As funções são geralmente chamadas na ordem primeiro a entrar, primeiro a sair; no entanto, os callbacks que têm um timeout especificado podem ser chamados fora de ordem, se necessário, para executá-los antes que o timeout acabe.

<script>
requestIdleCallback(() => {
    const script = document.createElement('script');
    script.src = 'javascript.js';
    document.head.appendChild(script);
});
</script>

Quando usar:

Use isso para scripts que são Nice to have ou para lidar com tarefas não críticas após a entrada do usuário

Vantagens:

  1. Executa o JavaScript com impacto mínimo para o usuário
  2. Muito provavelmente irá melhorar o INP

Desvantagens:

  1. Nenhuma garantia de que o código irá disparar em algum momento 

Método 15: Usar postTask

O método scheduler.postTask() permite que os usuários especifiquem opcionalmente um atraso mínimo antes da tarefa ser executada, uma prioridade para a tarefa, e um sinal que pode ser usado para modificar a prioridade da tarefa e/ou abortar a tarefa. Ele retorna uma promise que é resolvida com o resultado da função de callback da tarefa, ou rejeitada com o motivo do cancelamento ou um erro lançado na tarefa.

<script>
scheduler.postTask(() => {
    const script = document.createElement('script');
    script.src = 'javascript.js';
    document.head.appendChild(script);
}, { priority: 'background' });
</script>

Quando usar:

postTask é a API certa para agendar scripts quando você precisa de controle granular sobre a prioridade.

Vantagens:

  1. Controle total sobre o agendamento de execução do JavaScript!

Desvantagens:

  1. Não suportado no Safari. Suportado no Chrome 94+, Edge 94+ e Firefox 142+. Use feature detection e um fallback de setTimeout para cobertura total.

Método 16: Usar scheduler.yield()

scheduler.yield() é a maneira mais recente de dividir tarefas longas. Ele retorna uma promise que é resolvida em uma nova tarefa, dando ao navegador a chance de responder à entrada do usuário entre pedaços de trabalho. Ao contrário do setTimeout, a continuação obtém prioridade sobre outras tarefas na fila, de modo que seu código recomeça de onde parou sem ser empurrado para o final da fila.

<script>
async function processItems(items) {
    for (const item of items) {
        doWork(item);
        await scheduler.yield();
    }
}
</script>

Esta é a melhor ferramenta para melhorar o INP. Tarefas longas que bloqueiam a thread principal por centenas de milissegundos podem ser divididas em pedaços menores, cada um separado por um ponto de yield. O navegador pode lidar com a entrada do usuário em cada ponto de yield. Para um passo a passo prático desse padrão, veja como fazer yielding para a thread principal.

O Safari ainda não suporta scheduler.yield(), portanto, sempre inclua um fallback:

<script>
function yieldToMain() {
    if (globalThis.scheduler?.yield) {
        return scheduler.yield();
    }
    return new Promise(resolve => {
        setTimeout(resolve, 0);
    });
}

async function processItems(items) {
    for (const item of items) {
        doWork(item);
        await yieldToMain();
    }
}
</script>

Quando usar:

Use isso sempre que tiver um JavaScript de longa duração que bloqueia a thread principal. É a abordagem recomendada para melhorar o INP em manipuladores de interação e em qualquer código que processe dados em um loop.

Vantagens:

  1. Divide tarefas longas sem perder o seu lugar na fila
  2. A continuação é executada antes de outras tarefas na fila (ao contrário do setTimeout, que vai para o final da fila)
  3. Melhora diretamente o INP dando ao navegador uma chance de responder à entrada do usuário

Desvantagens:

  1. Não suportado no Safari. Suportado no Chrome 129+, Edge 129+ e Firefox 142+.
  2. Requer um fallback para cobertura total do navegador (o setTimeout funciona como um polyfill)

Após aplicar essas técnicas, verifique a melhoria com o Real User Monitoring. As pontuações do Lighthouse são um ponto de partida, mas os dados de campo de usuários reais são o que o Google usa para ranqueamento. O CoreDash rastreia o INP e todos os Core Web Vitals de visitantes reais, para que você possa ver se a sua estratégia de adiamento está realmente funcionando em produção.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Search Console reclamou do seu site?

Entrego uma lista priorizada de fixes baseada em dados de campo. Não um PDF de 50 páginas.

Solicitar auditoria
16 métodos para adiar ou agendar JavaScriptCore Web Vitals 16 métodos para adiar ou agendar JavaScript