Defer
Defer (от англ. defer - откладывать) - это атрибут HTML-тега <script>, который указывает браузеру загружать JavaScript-файл асинхронно, но выполнять его только после полной загрузки и разбора (парсинга) HTML-документа. Использование defer позволяет не блокировать рендеринг страницы, улучшая метрики FCP (First Contentful Paint) и LCP (Largest Contentful Paint).
Для маркетолога атрибут defer важен в том, как он способствует оптимизации скорости загрузки сайта, так как правильно настроенная загрузка JavaScript напрямую влияет на Core Web Vitals и, следовательно, на позиции в поисковой выдаче и конверсию.
Проблема блокировки рендеринга
[править]Когда браузер загружает HTML-страницу и встречает обычный тег <script src="script.js"> без атрибутов, он:
- Останавливает дальнейший парсинг (разбор) HTML
- Загружает указанный JavaScript-файл
- Выполняет его
- Только после этого продолжает парсить HTML
Это называется синхронной (блокирующей) загрузкой скриптов.
Последствия для пользователя:
- Пользователь видит пустой экран дольше необходимого
- Основной контент отображается с задержкой
- Ухудшаются метрики FCP и LCP
- Увеличивается показатель отказов
Как работает defer
[править]Атрибут defer меняет поведение браузера:
<script src="script.js" defer></script>
| Этап | Что происходит |
|---|---|
| 1. Парсинг HTML | Браузер продолжает парсить HTML без остановки, скрипт загружается в фоне |
| 2. Загрузка скрипта | Скрипт загружается параллельно с парсингом HTML |
| 3. Выполнение | Скрипт выполняется только после полного парсинга HTML-документа |
| 4. Порядок | Несколько скриптов с defer выполняются в том порядке, в котором они объявлены в коде |
Сравнение defer, async и обычной загрузки
[править]| Тип загрузки | Парсинг HTML | Загрузка скрипта | Выполнение |
|---|---|---|---|
| Обычный (без атрибутов) | Блокируется | Немедленно, блокирует парсинг | Немедленно после загрузки |
| async | Не блокируется | Параллельно с парсингом | Немедленно после загрузки (может блокировать парсинг) |
| defer | Не блокируется | Параллельно с парсингом | После полного парсинга HTML |
<!-- Обычная загрузка - блокирует рендеринг --> <script src="sync.js"></script> <!-- Async - загружается параллельно, выполняется сразу после загрузки --> <script src="async.js" async></script> <!-- Defer - загружается параллельно, выполняется после загрузки HTML --> <script src="defer.js" defer></script>
Визуальная схема работы
[править]Обычная загрузка:
[HTML парсинг] [Загрузка и выполнение скрипта] [HTML парсинг продолжается]
↓ ↓ ↓
Пользователь видит пустой экран → Контент появляется с задержкой
Defer:
[HTML парсинг] [HTML парсинг] [HTML парсинг] → [Выполнение скрипта]
↓ ↓ ↓ ↓
Загрузка скрипта в фоне → Пользователь видит контент быстрее
Когда использовать defer
[править]| Сценарий | Рекомендация |
|---|---|
| Скрипты, которые зависят от DOM | Использовать defer - гарантирует, что DOM уже загружен |
| Скрипты с зависимостями | Использовать defer - сохраняется порядок выполнения |
| Скрипты, не критичные для первого экрана | Использовать defer - не блокируют рендеринг |
| Скрипты аналитики (сбор данных) | Использовать defer или async - не блокируют пользователя |
Когда НЕ использовать defer
[править]| Сценарий | Причина |
|---|---|
| Скрипты, критичные для первого экрана | Если скрипт нужен для отображения основного контента, лучше встроить его напрямую (inline) |
| Очень маленькие скрипты | Накладные расходы на асинхронную загрузку могут превышать выгоду |
| Скрипты, которые должны выполниться до парсинга | Например, модификация DOM до того, как пользователь увидит страницу |
Инструменты для анализа загрузки скриптов
[править]| Инструмент | Назначение |
|---|---|
| Chrome DevTools (Network) | Отображает загрузку скриптов и их влияние на рендеринг |
| Lighthouse | Аудит, предупреждающий о блокирующих рендеринг скриптах |
| WebPageTest | Детальный анализ загрузки ресурсов на реальных устройствах |
Пример оптимизации
[править]До оптимизации:
<head> <script src="jquery.js"></script> <!-- блокирует рендеринг --> <script src="analytics.js"></script> <!-- блокирует рендеринг --> <script src="app.js"></script> <!-- блокирует рендеринг --> </head>
После оптимизации:
<head> <!-- Критический inline-скрипт для первого экрана --> <script>/* критический код */</script> <!-- Не критические скрипты с defer --> <script src="jquery.js" defer></script> <script src="analytics.js" defer></script> <script src="app.js" defer></script> </head>
Влияние на Core Web Vitals
[править]| Метрика | Как влияет defer |
|---|---|
| FCP (First Contentful Paint) | Улучшается - браузер не ждёт скрипты для отображения первого контента |
| LCP (Largest Contentful Paint) | Улучшается - основной контент загружается быстрее |
| INP (Interaction to Next Paint) | Defer позволяет основному потоку быстрее обрабатывать пользовательские взаимодействия, снижая задержку реакции на клики и нажатия клавиш |
Совместимость с браузерами
[править]Атрибут defer поддерживается всеми современными браузерами:
- Google Chrome - с версии 1.0
- Mozilla Firefox - с версии 3.5
- Safari - с версии 5.0
- Microsoft Edge - с версии 12
- Internet Explorer - с версии 10
Связь с другими техниками оптимизации
[править]| Техника | Взаимодействие с defer |
|---|---|
| Critical CSS | Дополняют друг друга - CSS не блокирует рендеринг, скрипты тоже не блокируют |
| Code Splitting | Разделённые чанки можно загружать с defer |
| Preload | Можно использовать preload для важных скриптов, а defer для некритичных |
