JavaScript — палка о двух концах. С одной стороны, он делает сайты интерактивными: формы, слайдеры, корзина, динамическая подгрузка. С другой — именно JavaScript чаще всего тормозит загрузку страниц. Обычный тег script без атрибутов блокирует парсинг HTML: браузер доходит до скрипта, останавливается, скачивает его, выполняет, и только потом продолжает разбирать страницу. Если скрипт большой и лежит в head, пользователь видит белый экран несколько секунд. Атрибуты defer и async решают эту проблему: скрипты загружаются параллельно с HTML и не блокируют отрисовку. Разница между defer и async тонкая, но принципиальная. Неправильное использование может сломать работу скриптов. В этой статье разберём, как работают defer и async, когда какой использовать и как проверить, что скрипты оптимизированы.
Как браузер загружает скрипты без defer и async
По умолчанию тег script без атрибутов работает так: браузер парсит HTML, доходит до script, приостанавливает парсинг, скачивает скрипт, выполняет его, и только после этого продолжает парсить HTML. Это называется блокирующей загрузкой. Если скрипт в head, а он весит 500 КБ и скачивается 2 секунды — пользователь смотрит на белый экран 2 секунды, прежде чем страница начнёт отображаться. Если скриптов несколько, задержки суммируются. Для SEO это критично: медленная отрисовка первого экрана ухудшает LCP (Largest Contentful Paint), один из показателей Core Web Vitals. Google использует Core Web Vitals как фактор ранжирования. Значит, неоптимизированные скрипты напрямую вредят позициям. Решение — использовать defer или async для скриптов, которые не критичны для отрисовки первого экрана. Но важно понимать разницу между ними.
Что делает defer: отложенное выполнение
Атрибут defer указывает браузеру: скачивай скрипт параллельно с парсингом HTML, но выполняй только после того, как HTML полностью разобран. Скрипт с defer: скачивается параллельно с парсингом → парсинг HTML завершается → скрипт выполняется. Главное преимущество: парсинг не блокируется, страница отображается быстрее. Второе преимущество: порядок выполнения сохраняется. Если несколько скриптов с defer, они выполняются в том порядке, в котором стоят в HTML. Это важно, если один скрипт зависит от другого (например, jQuery и плагин на jQuery). Третье преимущество: defer-скрипты выполняются до события DOMContentLoaded, что даёт уверенность, что DOM уже готов. Когда использовать defer: для скриптов, которые не участвуют в отрисовке первого экрана, но должны выполниться в определённом порядке. Например: аналитика, подгрузка контента, обработчики событий, скрипты в footer. Проверить, использует ли ваш сайт defer, можно через Проверка defer и async.
Что делает async: параллельная загрузка и немедленное выполнение
Атрибут async указывает браузеру: скачивай скрипт параллельно с парсингом HTML и выполняй сразу, как только он скачается. Скрипт с async: скачивается параллельно → как только скачался, выполняется (парсинг приостанавливается на время выполнения) → парсинг продолжается. Разница с defer: async не сохраняет порядок выполнения. Если два async-скрипта, тот, что скачался раньше, выполнится раньше, независимо от порядка в HTML. Это опасно для скриптов с зависимостями. Когда использовать async: для независимых скриптов, которые не зависят от других и не требуют готового DOM. Например: сторонние виджеты (реклама, счётчики, чаты), скрипты аналитики, которые работают автономно. Не использовать async: для jQuery и плагинов к нему, для скриптов, которые модифицируют DOM, для скриптов, зависящих от порядка выполнения. Проверить, как загружаются скрипты на вашем сайте, можно через Проверка defer и async.
Defer vs async: сравнительная таблица
Ключевые различия. Порядок выполнения: defer — в порядке HTML, async — в порядке загрузки. Момент выполнения: defer — после парсинга HTML, async — сразу после загрузки. Блокировка парсинга: defer — не блокирует, async — блокирует на время выполнения. DOMContentLoaded: defer — выполняется до него, async — может выполниться после. Зависимости: defer — поддерживает, async — не поддерживает. Когда использовать: defer — для скриптов с зависимостями и работой с DOM, async — для независимых скриптов. Правило простое: если сомневаетесь — используйте defer. Он безопаснее. Async — только для независимых сторонних скриптов. Подробнее об оптимизации JavaScript читайте в статье Оптимизация JavaScript и CSS для скорости.
Как правильно разместить скрипты для ускорения страницы
Первое правило: не держите скрипты в head без необходимости. Скрипты в head блокируют отрисовку. Переместите их в конец body или используйте defer. Второе правило: критический JavaScript (тот, без которого первый экран не работает) — оставьте в head без defer, но минимальный. Это может быть скрипт, который рисует меню или подгружает основную картинку. Всё остальное — defer или async. Третье правило: не подключайте jQuery ради пары функций. jQuery весит 30-90 КБ. Если можно обойтись нативным JavaScript — обходитесь. Четвёртое правило: объединяйте мелкие скрипты в один файл (для HTTP/1.1) или оставляйте раздельно (для HTTP/2). Пятое правило: минифицируйте скрипты — уберите пробелы, комментарии, неиспользуемый код. Сжатый скрипт весит в 2-3 раза меньше. Проверить размер скриптов можно через Проверка размера страницы. Шестое правило: используйте модули ES6 с type=module — они работают как defer по умолчанию.
Типичные ошибки при использовании defer и async
Ошибка первая: defer на критическом скрипте. Если скрипт отвечает за отрисовку первого экрана (например, строит лейаут), defer отложит его выполнение, и пользователь увидит несобранную страницу. Решение: для критических скриптов используйте обычную загрузку в head или inline-скрипт. Ошибка вторая: async на зависимых скриптах. Если jQuery и плагин загружаются с async, плагин может выполниться раньше jQuery и упасть с ошибкой. Решение: для зависимых скриптов используйте defer. Ошибка третья: defer на скриптах с document.write. document.write не работает с defer и async — такие скрипты будут проигнорированы или выполнятся некорректно. Решение: уберите document.write, замените на современные методы. Ошибка четвёртая: inline-скрипты, зависящие от defer-скриптов. Если inline-скрипт в head использует функцию из defer-скрипта, эта функция ещё не определена. Решение: переносите inline-скрипты в конец body или оборачивайте в DOMContentLoaded. Ошибка пятая: не проверять результат. Добавили defer на скрипты, но не проверили, что сайт работает. Решение: после оптимизации прогоните ключевые сценарии: форма отправляется, корзина работает, аналитика собирает данные.
Как проверить, что defer и async настроены правильно
Первый шаг — инструмент Проверка defer и async. Он покажет, какие скрипты на странице имеют defer, какие async, а какие грузятся блокирующе. Второй шаг — инструменты разработчика: F12 → Network → посмотрите, как загружаются скрипты. Блокирующие скрипты видны как ресусры, которые загружаются до начала отрисовки. Третий шаг — проверьте Core Web Vitals: LCP должен улучшиться после оптимизации. Используйте Скорость загрузки и Core Web Vitals для измерения. Четвёртый шаг — проверьте функциональность: работают ли формы, кнопки, слайдеры, меню. Оптимизация не должна ломать сайт. Пятый шаг — мониторьте ошибки в консоли браузера (F12 → Console). Если после оптимизации появились ошибки JavaScript — что-то пошло не так, нужно откатить и разбираться.
Defer, async и Core Web Vitals
Правильная настройка загрузки скриптов напрямую влияет на Core Web Vitals. LCP (Largest Contentful Paint): блокирующие скрипты задерживают отрисовку первого экрана, откладывая LCP. defer и async позволяют браузеру быстрее начать отрисовку, улучшая LCP. CLS (Cumulative Layout Shift): скрипты, которые динамически вставляют контент после загрузки, могут вызвать сдвиги макета. С defer-скриптами, которые выполняются после парсинга, риск сдвигов ниже. INP (Interaction to Next Paint): долго выполняющиеся скрипты задерживают реакцию на действия пользователя. Оптимизация загрузки и выполнение скриптов — это часть работы над INP. Полный гайд по Core Web Vitals есть в статье Скорость загрузки сайта. Используйте Проверка TTFB для замера скорости ответа сервера.
Часто задаваемые вопросы
Что лучше: defer или async?
Для большинства скриптов лучше defer — он сохраняет порядок выполнения и выполняет скрипты после готовности DOM. Async подходит только для независимых сторонних скриптов (виджеты, счётчики), которым не важны порядок и DOM.
Как проверить, использует ли сайт defer и async?
Используйте инструмент проверки defer и async в SerpMax. Он покажет, какие скрипты загружаются с defer, какие с async, а какие блокирующе без атрибутов.
Влияет ли оптимизация скриптов на SEO?
Да. Блокирующие скрипты замедляют отрисовку страницы, что ухудшает Core Web Vitals. А Core Web Vitals — официальный фактор ранжирования Google. Косвенно оптимизация скриптов помогает позициям.
Можно ли добавлять defer на все скрипты?
Нет. Критические скрипты, отвечающие за отрисовку первого экрана, должны загружаться без defer. Также defer не работает с document.write. Для остальных скриптов defer — безопасный выбор.