Атрибут async при загрузке скриптов
Атрибут async указывает браузеру загружать JavaScript скрипт асинхронно, параллельно с парсингом HTML, что улучшает производительность страницы.
Как работает async?
Без async (синхронная загрузка):
HTML parsing -> Script request -> Script download -> Script execution -> HTML parsing
Браузер полностью останавливает парсинг HTML при встрече со скриптом, загружает его, выполняет, и только потом продолжает.
С async (асинхронная загрузка):
HTML parsing -> Script request (в фоне)
HTML parsing (продолжается) <- Script download завершена -> Script execution -> HTML parsing
Браузер загружает скрипт в фоне, одновременно продолжая парсить HTML. Когда скрипт загружен, выполнение паузирует парсинг для его выполнения.
Синтаксис
<script async src="https://example.com/script.js"></script>
Как это работает в деталях
Фаза 1: Инициирование загрузки
<!DOCTYPE html>
<html>
<head>
<script async src="analytics.js"></script>
</head>
<body>
<h1>Заголовок</h1>
</body>
</html>
Браузер начинает загружать analytics.js, но одновременно продолжает парсить DOM.
Фаза 2: Параллельное выполнение
Время загрузки скрипта непредсказуемо:
Момент 0ms: Парсинг: <h1>, <p>, загрузка скрипта начата
Момент 500ms: Парсинг: <div>, <form>, скрипт всё ещё загружается
Момент 800ms: Скрипт загружен -> ПАУЗИРУЕМ парсинг -> выполнение скрипта
Момент 850ms: Скрипт выполнен -> ПРОДОЛЖАЕМ парсинг
Момент 1200ms: Парсинг завершён
Практический пример
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Async Loading Demo</title>
<script async src="https://cdn.example.com/tracker.js"></script>
</head>
<body>
<h1>Главное содержимое страницы</h1>
<p>Это видимо сразу, не дожидаясь загрузки скрипта tracker.js</p>
<script>
console.log("Inline скрипт выполнен");
</script>
</body>
</html>
Страница отрендерится быстрее, даже если tracker.js медленный.
Варианты загрузки скриптов
1. Синхронная (default)
<script src="script.js"></script>
Парсинг блокируется до выполнения скрипта.
2. Async
<script async src="script.js"></script>
Скрипт загружается параллельно, выполняется когда готов. Порядок выполнения не гарантирован.
3. Defer
<script defer src="script.js"></script>
Скрипт загружается параллельно, но выполняется после полного парсинга HTML. Порядок выполнения гарантирован.
Сравнение режимов
| Загрузка | Выполнение | Порядок | Использование
-------------|----------|------------|---------|---------------
Sync | Блокирует| Блокирует | Да | Редко (legacy)
Async | Параллель| АСАП | Нет | Analytics, 3rd-party
Defer | Параллель| После HTML | Да | App логика
Когда использовать async?
Хорошо для async:
- Аналитика (Google Analytics, Metrica)
- Реклама (AdSense, Yandex.Ads)
- Чат боты
- Скрипты третьих сторон, которые не критичны для страницы
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>
<script async src="https://mc.yandex.ru/metrika/tag.js"></script>
Плохо для async:
- Главная логика приложения (используй defer)
- Скрипты, от которых зависят другие скрипты
- Код, который должен выполниться в определённом порядке
Обработка готовности
Поскольку async скрипт может загрузиться в любой момент, нужна обработка:
<script async src="api.js"></script>
<script>
function useAPI() {
if (typeof window.API !== 'undefined') {
window.API.init();
} else {
setTimeout(useAPI, 100);
}
}
useAPI();
</script>
Обычно это встроено в код скрипта:
window.dispatchEvent(new Event('api-loaded'));
Практические советы
- Используй async для некритичных скриптов
- Используй defer для основной логики приложения
- Несколько async скриптов загружаются параллельно
- Несколько defer скриптов выполняются в порядке определения