Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Атрибут defer: Отложенное выполнение скриптов
Атрибут defer — это логический атрибут тега <script>, который указывает браузеру, что скрипт должен быть загружен параллельно с парсингом HTML-документа, но его выполнение должно быть отложено до момента полной загрузки и построения DOM-дерева (но до события DOMContentLoaded).
Ключевые особенности работы defer
-
Параллельная загрузка без блокировки парсинга Скрипт начинает загружаться немедленно при встрече тега
<script>, но не блокирует парсинг остальной части документа:<script defer src="script.js"></script> <!-- Парсинг HTML продолжается параллельно с загрузкой script.js --> -
Выполнение в порядке объявления Все скрипты с
deferвыполняются строго в том порядке, в котором они указаны в HTML-документе, независимо от того, какой из них загрузился первым:<script defer src="library.js"></script> <script defer src="app.js"></script> <!-- Гарантировано: library.js выполнится перед app.js --> -
Выполнение после построения DOM, но до
DOMContentLoadedСкрипты сdeferвыполняются после полного парсинга документа, но до того, как сработает событиеDOMContentLoaded:// В script.js с defer: console.log(document.querySelector('p')); // Уже будет доступен элемент document.addEventListener('DOMContentLoaded', () => { console.log('DOM готов'); // Выполнится ПОСЛЕ этого кода });
Сравнение с атрибутом async
Чтобы лучше понять defer, полезно сравнить его с другим атрибутом — async:
| Характеристика | defer | async |
|---|---|---|
| Порядок выполнения | Сохраняет порядок объявления | Выполняется по готовности (порядок не гарантирован) |
| Момент выполнения | После парсинга HTML, до DOMContentLoaded | Сразу после загрузки, может прервать парсинг |
| Зависимости между скриптами | Идеально подходит, когда скрипты зависят друг от друга | Не подходит для зависимых скриптов |
| Использование с DOM | Гарантирует доступность DOM-дерева | Нет гарантии готовности DOM |
Практические сценарии использования
Когда использовать defer:
- Скрипты, которым требуется полный доступ к DOM (манипуляции с элементами)
- Библиотеки и их зависимые модули (например, jQuery + плагины)
- Основная бизнес-логика приложения, которая зависит от структуры страницы
Пример типичного использования:
<!DOCTYPE html>
<html>
<head>
<script defer src="vendor/jquery.min.js"></script>
<script defer src="vendor/jquery-plugin.js"></script>
<script defer src="main.js"></script>
</head>
<body>
<div id="content">Загрузка...</div>
<!-- DOM будет построен до выполнения скриптов -->
</body>
</html>
Важные технические детали
-
Атрибут
deferигнорируется для inline-скриптов (без атрибутаsrc):<script defer> console.log('Это выполнится немедленно!'); // defer игнорируется </script> -
Совместимость с
type="module": Для модульных скриптов поведениеdeferустановлено по умолчанию:<script type="module" src="module.js"></script> <!-- Автоматически ведёт себя как defer --> -
Историческая поддержка: В старых браузерах (IE < 10)
deferимел несколько иное поведение, но в современных реализован согласно спецификации HTML5.
Оптимизация производительности
Использование defer — одна из ключевых техник оптимизации критического пути рендеринга:
- Ускоряет время до First Contentful Paint (FCP)
- Уменьшает время блокировки парсинга
- Позволяет браузеру быстрее отобразить видимую часть страницы
Рекомендация: Для большинства внешних скриптов, особенно в конце <head>, предпочтительнее использовать defer вместо стандартного выполнения (без атрибутов) или async, если только нет специфических требований к моментальному выполнению.
Таким образом, defer представляет собой баланс между необходимостью выполнения JavaScript и оптимизацией воспринимаемой производительности веб-страницы, обеспечивая предсказуемый порядок выполнения при максимально параллельной загрузке ресурсов.