Как управлять очередностью загрузки и выполнения скриптов в JavaScript
Что проверяют
Знаете ли вы, как браузер обрабатывает <script> при разборе HTML и чем отличаются async, defer и модули. Промисы и async/await здесь вторичны: вопрос про загрузку, а не про асинхронный код внутри скрипта. Следом часто спрашивают, как подгрузить скрипт динамически и сохранить порядок.
Как отвечать
- обычный
<script src>: парсер останавливается, скрипт загружается и выполняется, потом разбор HTML продолжается. Поэтому такие скрипты ставят в конец<body>или помечаютdefer; defer: загрузка идёт параллельно с разбором, выполнение после разбора документа, строго в порядке следования в разметке и до событияDOMContentLoaded. У встроенных скриптов безsrcатрибут игнорируется;async: загрузка параллельно, выполнение сразу по готовности, разбор на это время прерывается. Порядок не гарантирован, подходит для независимого кода вроде аналитики;type="module": модули по умолчанию ведут себя какdefer, а сasyncвыполняются сразу после загрузки самого модуля и его зависимостей. Порядок внутри задаёт графimport;- динамические скрипты: элемент из
document.createElement('script')по умолчанию выполняется какasync. Чтобы сохранить порядок вставки, ставятscript.async = falseили ждутonloadпредыдущего; import(): динамический импорт возвращает промис, так грузят тяжёлые модули по требованию, а бандлер выносит их в отдельный чанк.
Ускорить загрузку помогают <link rel="preload"> и <link rel="modulepreload">, приоритет подсказывает атрибут fetchpriority. В проектах на Vite или webpack порядок выполнения задают импорты, а не ручная расстановка тегов.
Где спотыкаются
Считают, что defer выполняется после события load. На деле раньше: до DOMContentLoaded, когда картинки могут ещё грузиться.
Думают, что несколько скриптов с async выполнятся в порядке разметки. Если второй зависит от первого, это гонка, которая проявится на медленной сети.
Отвечают про промисы и цикл событий вместо атрибутов тега. Цепочка await loadScript() рабочая, но это частный случай, и без понимания defer она выглядит как изобретение велосипеда.