Атрибут async у script
async, це атрибут для <script>, який каже браузеру завантажити скрипт асинхронно, паралельно з HTML, і виконати його одразу після завантаження, не чекаючи на побудову DOM та на інші скрипти. Це найшвидший, але й найменш передбачуваний спосіб підключення, бо порядок виконання файлів не гарантований.
Теорія
TL;DR
asyncзавантажує зовнішній скрипт паралельно з розбором HTML, парсинг при цьому не зупиняється.- Щойно файл завантажився, він виконується негайно, навіть якщо HTML ще не дочитано.
- Виконання може на короткий час перервати парсинг сторінки.
- Порядок кількох
async-скриптів довільний, він залежить від швидкості мережі. asyncтаdeferдіють тільки для зовнішніх скриптів зsrc, інлайнові їх ігнорують.- Використовуйте
asyncдля незалежного коду (аналітика, реклама, віджети), аdeferдля основної логіки сайту.
Швидкий приклад
<head>
<!-- незалежний скрипт: качається у фоні і стартує щойно готовий -->
<script src="analytics.js" async></script>
</head>Як працює звичайний <script>
<script src="app.js"></script>Що робить браузер:
- Починає читати HTML.
- Зустрічає
<script>. - Зупиняє парсинг HTML.
- Завантажує
app.js. - Виконує
app.js. - Продовжує читати HTML далі.
Тобто звичайний <script> блокує завантаження сторінки до моменту виконання.
Що робить async
<script src="app.js" async></script>Тепер:
- Браузер продовжує завантажувати HTML.
- Паралельно завантажує
app.jsу фоні. - Щойно
app.jsзавантажився, одразу виконує його, навіть якщо HTML ще не закінчено.
Тобто:
- завантаження асинхронне;
- виконання миттєве;
- порядок з іншими скриптами не гарантується.
Візуально це виглядає так:
HTML: |-----парсинг-----|-------->
JS: |--завантаження--|виконання|HTML і JS вантажаться паралельно, але виконання JS може перервати HTML-парсинг, якщо скрипт завершить завантаження раніше.
Відмінність від defer
| Атрибут | Коли виконується скрипт | Порядок | Блокує HTML | Коли використовувати |
|---|---|---|---|---|
| (без атрибута) | Одразу при зустрічі | По порядку | Так | Старий inline-код |
async | Одразу після завантаження | Випадковий | Може перервати | Незалежні скрипти (аналітика, реклама) |
defer | Після побудови DOM | По порядку | Ні | Основний код сайту |
Головне:
async, це «запускай, коли готовий, не чекай нікого»;defer, це «чекай, поки DOM побудується, потім запускай по порядку».
Зведена таблиця властивостей:
| Властивість | async | defer |
|---|---|---|
| Завантажує паралельно з HTML | Так | Так |
| Виконує, щойно завантажиться | Так | Ні |
| Чекає на готовність DOM | Ні | Так |
| Зберігає порядок скриптів | Ні | Так |
| Блокує парсинг HTML під час виконання | Так, може перервати | Ні |
| Ідеально для | Незалежних скриптів (аналітика, реклама, віджети) | Основної логіки сайту |
Кілька async-скриптів
<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>) ці атрибути ігнорують.
Приклад правильного підключення:
<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-скрипта. Подія може спрацювати раніше, ніж такий файл завантажиться.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.