Skip to main content

Чим "defer" відрізняється від "async" у <script>?

Проблема, яку вирішують defer і async

Коли браузер зустрічає тег:

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

за умовчанням він:

  1. Зупиняє парсинг HTML,
  2. Завантажує script.js,
  3. Виконує його,
  4. Тільки потім продовжує будувати DOM.

Це блокує рендер сторінки -> користувач бачить "порожній екран", поки JS не завантажиться. Тому з'явилися атрибути defer і async, щоб не блокувати HTML-парсинг.


defer

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

Як це працює:

  1. Скрипт завантажується паралельно з HTML (асинхронно).
  2. Але виконується тільки після повного парсингу HTML - тобто коли DOM готовий, але до події DOMContentLoaded.
  3. Скрипти з defer виконуються у порядку, у якому вони вказані в HTML.

Чудово підходить для "основних" скриптів застосунку (наприклад, main.js, vendor.js).

Приклад:

javascript
<script src="a.js" defer></script> <script src="b.js" defer></script>

Спочатку завантажаться обидва паралельно, але виконаються строго по порядку: a.js -> b.js після побудови DOM.


async

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

Як це працює:

  1. Скрипт завантажується паралельно з HTML (як defer),
  2. Але виконується одразу після завантаження, навіть якщо HTML ще не допарсено.
  3. Скрипти з async виконуються у непередбачуваному порядку,
  • залежно від того, який швидше завантажиться.

Підходить для незалежних скриптів (наприклад, аналітика, реклама, метрики).

Приклад:

javascript
<script src="a.js" async></script> <script src="b.js" async></script>

b.js може виконатися раніше, якщо завантажився швидше, навіть якщо в HTML він був нижче.


Порівняння defer і async

Властивістьdeferasync
Завантаження скриптаАсинхронно (паралельно з HTML)Асинхронно
ВиконанняПісля повного парсингу HTMLОдразу після завантаження
Порядок виконанняЗберігаєтьсяНе гарантується
Блокує HTML-парсингНіНі
Подія DOMContentLoadedЧекає виконання всіх defer-скриптівНе чекає
Типові сценаріїОсновна логіка сайтуЗовнішні трекери, реклама

Приклад візуально

javascript
<!-- HTML парситься... --> <script src="main.js" defer></script> <script src="analytics.js" async></script>

Процес:

ЕтапЩо відбувається
1Браузер починає парсити HTML
2Одночасно завантажує обидва скрипти
3analytics.js (async) завантажується швидше -> виконується одразу
4HTML парситься до кінця
5Потім виконується main.js (defer)
6Потім спрацьовує DOMContentLoaded

Висновки

АтрибутКоли використовувати
deferДля основного JS-коду, який залежить від DOM (наприклад, ініціалізація інтерфейсу)
asyncДля незалежних скриптів (аналітика, метрики, реклама)
Без атрибутівТільки якщо потрібно заблокувати парсинг HTML (рідко потрібно)

Порада

Якщо ти використовуєш сучасний bundler (Next.js, Vite, Webpack) - він сам ставить defer для <script> у head, тому в сучасних застосунках це вже best practice за умовчанням.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.