Події:
DOMContentLoaded- HTML повністю розібрано, DOM готовий. Зображення, стилі (крім тих, що блокують скрипти) й iframe ще можуть вантажитися. Тут зазвичай ініціалізують скрипти.load(наwindow) - завантажено все: зображення, шрифти, iframe. Відбувається пізніше, часто значно.
Звичайний <script src> у <head> зупиняє розбір HTML, доки скрипт не завантажиться й не виконається. Сторінка «біла», а скрипт ще й не бачить елементи нижче.
defer- завантажити паралельно з розбором, а виконати після розбору HTML, передDOMContentLoaded, у порядку появи в документі.async- завантажити паралельно й виконати, щойно завантажився, у довільному порядку, перериваючи розбір.
<script defer src="/app.js"></script> <!-- основний код, залежить від DOM -->
<script async src="/analytics.js"></script> <!-- незалежний, порядок не важливий -->
<script type="module" src="/main.js"></script> <!-- модулі поводяться як defer -->
Правило: код застосунку - defer (або type="module"), незалежні сторонні скрипти (аналітика, віджети) - async. Розміщувати скрипти в кінці <body> - старий спосіб досягти схожого ефекту; з defer у цьому немає потреби.