defer e async mudam quando um <script> externo é baixado e executado em relação ao parsing HTML. Ambos permitem que o script seja baixado em paralelo sem bloquear o parser — a diferença está no tempo de execução.
html
defer e async mudam quando um <script> externo é baixado e executado em relação ao parsing HTML. Ambos permitem que o script seja baixado em paralelo sem bloquear o parser — a diferença está no tempo de execução.
Normal: parse──stop──[download+exec]──parse──────── (slowest)
async: parse──────────────────exec──parse──────── (runs whenever it arrives)
defer: parse───────────────────────────parse──exec (after parsing, before DOMContentLoaded)
async | defer | |
|---|---|---|
| Download | paralelo | paralelo |
| Executa | assim que baixado | após HTML totalmente analisado |
| Ordem preservada? | Não (quem terminar primeiro) | Sim (ordem do documento) |
| Bloqueia parser? | apenas brevemente durante exec | nunca |
defer — para scripts que tocam o DOM ou dependem uns dos outros/ordem (código da app). Executam após o DOM existir, em sequência, logo antes de DOMContentLoaded.async — para scripts de terceiros independentes que não dependem do DOM ou de outros scripts (analytics, anúncios). Ordem não importa, execute-os ASAP.<script src="analytics.js" async></script> <!-- independent → async -->
<script src="app.js" defer></script> <!-- app logic, ordered → defer -->
Nota: ambos se aplicam apenas a scripts externos (src); são ignorados em scripts inline. Módulos ES (type="module") são deferidos por padrão.
Usar defer/async evita que scripts bloqueiem o parsing HTML, o que melhora diretamente o desempenho de carregamento e First Contentful Paint.
Escolher a correta (defer para código de app ordenado dependente de DOM, async para scripts de terceiros que não requerem interação) evita tanto carregamentos lentos quanto bugs de dependência de ordem.