Загрузка скриптов: async, defer, module
↑ 1.2 HTML · ← Предыдущая · → Следующая
Зачем это на собесе
Критично для производительности: как скрипты блокируют рендер и чем отличаются
asyncиdefer.
Объяснение
Обычный <script> блокирует парсинг HTML: браузер скачивает и выполняет его, затем продолжает.
| Атрибут | Загрузка | Выполнение | Порядок |
|---|---|---|---|
| (нет) | блокирует парсинг | сразу | по порядку |
async | параллельно | сразу после загрузки (может прервать парсинг) | не гарантирован |
defer | параллельно | после парсинга, до DOMContentLoaded | по порядку |
type="module" | параллельно | как defer; строгий режим, свой scope, поддержка import | по порядку |
nomodule | для старых браузеров |
<script src="analytics.js" async></script> <!-- независимые скрипты -->
<script src="app.js" defer></script> <!-- зависят от DOM/порядка -->
<script type="module" src="/src/main.js"></script>
<script type="module">import { init } from "./app.js"; init();</script>Также: preload для критичных ресурсов, modulepreload, динамический import() для код-сплиттинга, fetchpriority="high", размещение скриптов в конце <body> (устаревший приём, заменён defer).
Нюансы и подводные камни
asyncдля скриптов, зависящих друг от друга, приводит к гонкам порядка.deferиasyncне работают для inline-скриптов (безsrc).type="module"выполняется в строгом режиме,thisна верхнем уровне —undefined.- Модули подчиняются CORS, при
file://могут не работать. - Сторонние скрипты (метрики, чаты) — главный источник блокировок: загружайте
asyncили по бездействию.
Практика
- Сравните загрузку страницы с обычным,
deferиasyncскриптом в Performance. - Отложите загрузку виджета до
requestIdleCallback. - Добавьте
preloadдля критичного шрифта/скрипта и измерьте LCP.
Вопросы с ответами
Чем async отличается от defer?
asyncвыполняется как только скачан, порядок не гарантирован;defer— после парсинга и в порядке подключения.
Когда использовать module?
Для современных приложений с
import/export; ведёт себя какdefer.