Skip to main content

Атрибут async у script

async, це атрибут для <script>, який каже браузеру завантажити скрипт асинхронно, паралельно з HTML, і виконати його одразу після завантаження, не чекаючи на побудову DOM та на інші скрипти. Це найшвидший, але й найменш передбачуваний спосіб підключення, бо порядок виконання файлів не гарантований.

Теорія

TL;DR

  • async завантажує зовнішній скрипт паралельно з розбором HTML, парсинг при цьому не зупиняється.
  • Щойно файл завантажився, він виконується негайно, навіть якщо HTML ще не дочитано.
  • Виконання може на короткий час перервати парсинг сторінки.
  • Порядок кількох async-скриптів довільний, він залежить від швидкості мережі.
  • async та defer діють тільки для зовнішніх скриптів з src, інлайнові їх ігнорують.
  • Використовуйте async для незалежного коду (аналітика, реклама, віджети), а defer для основної логіки сайту.

Швидкий приклад

html
<head> <!-- незалежний скрипт: качається у фоні і стартує щойно готовий --> <script src="analytics.js" async></script> </head>

Як працює звичайний <script>

html
<script src="app.js"></script>

Що робить браузер:

  1. Починає читати HTML.
  2. Зустрічає <script>.
  3. Зупиняє парсинг HTML.
  4. Завантажує app.js.
  5. Виконує app.js.
  6. Продовжує читати HTML далі.

Тобто звичайний <script> блокує завантаження сторінки до моменту виконання.

Що робить async

html
<script src="app.js" async></script>

Тепер:

  1. Браузер продовжує завантажувати HTML.
  2. Паралельно завантажує app.js у фоні.
  3. Щойно app.js завантажився, одразу виконує його, навіть якщо HTML ще не закінчено.

Тобто:

  • завантаження асинхронне;
  • виконання миттєве;
  • порядок з іншими скриптами не гарантується.

Візуально це виглядає так:

text
HTML: |-----парсинг-----|--------> JS: |--завантаження--|виконання|

HTML і JS вантажаться паралельно, але виконання JS може перервати HTML-парсинг, якщо скрипт завершить завантаження раніше.

Відмінність від defer

АтрибутКоли виконується скриптПорядокБлокує HTMLКоли використовувати
(без атрибута)Одразу при зустрічіПо порядкуТакСтарий inline-код
asyncОдразу після завантаженняВипадковийМоже перерватиНезалежні скрипти (аналітика, реклама)
deferПісля побудови DOMПо порядкуНіОсновний код сайту

Головне:

  • async, це «запускай, коли готовий, не чекай нікого»;
  • defer, це «чекай, поки DOM побудується, потім запускай по порядку».

Зведена таблиця властивостей:

Властивістьasyncdefer
Завантажує паралельно з HTMLТакТак
Виконує, щойно завантажитьсяТакНі
Чекає на готовність DOMНіТак
Зберігає порядок скриптівНіТак
Блокує парсинг HTML під час виконанняТак, може перерватиНі
Ідеально дляНезалежних скриптів (аналітика, реклама, віджети)Основної логіки сайту

Кілька async-скриптів

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

Вони можуть виконатися в будь-якому порядку, це залежить від того, який файл завантажиться раніше. Тому якщо b.js розраховує на глобальні змінні з a.js, така пара рано чи пізно зламається на повільній мережі.

Ще один наслідок: async-скрипт може стартувати до того, як з'явиться потрібний йому елемент розмітки. Якщо код торкається DOM, або ставте defer, або обгортайте роботу в обробник DOMContentLoaded.

Правильне підключення в <head>

async і defer працюють тільки для зовнішніх скриптів (src="..."). Вбудовані (<script>...</script>) ці атрибути ігнорують.

Приклад правильного підключення:

html
<head> <script src="vendor.js" async></script> <script src="main.js" defer></script> </head>

Тут analytics-подібний vendor.js незалежний, його можна запустити одразу, а main.js залежить від DOM, тому виконається після його побудови.

Запам'ятай просто: async, це «завантаж і виконай якнайшвидше», defer, це «завантаж заздалегідь, але зачекай, поки DOM готовий».

Типові помилки

  • Ставити async на скрипти, що залежать один від одного. Порядок випадковий, і залежність зламається несподівано.
  • Працювати з DOM у async-скрипті. Потрібного елемента може ще не існувати; беріть defer або чекайте DOMContentLoaded.
  • Писати async на інлайновому скрипті. Без src атрибут не має жодного ефекту.
  • Вважати, що async взагалі не блокує сторінку. Завантаження не блокує, але виконання може перервати парсинг HTML.
  • Ставити async на основний бандл застосунку. Він майже завжди залежить від DOM і від порядку, тому це робота для defer.
  • Розраховувати, що DOMContentLoaded дочекається async-скрипта. Подія може спрацювати раніше, ніж такий файл завантажиться.

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

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

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