\n```\n\n### Решение: атрибуты `async` и `defer`\n\nОба атрибута заставляют браузер загружать скрипт **асинхронно**, не останавливая парсинг HTML. Однако они кардинально различаются моментом выполнения.\n\n#### Атрибут `async`\n\nСкрипт с `async` выполняется **как только загрузится**, при этом парсинг HTML приостанавливается на время его выполнения. Порядок выполнения не гарантирован — какой скрипт загрузится первым, тот и запустится.\n\n```html\n\n\n\n```\n\n**Идеальное применение:** для абсолютно независимых скриптов, например, аналитики, рекламных баннеров, виджетов соцсетей, которые не зависят от DOM или других скриптов.\n\n#### **Атрибут `defer`** — подробный разбор\n\n**`defer`** — это более предсказуемый и безопасный вариант. Он указывает браузеру:\n\n1. **Загружать** скрипт немедленно, в фоновом режиме, параллельно с парсингом HTML.\n2. **Отложить выполнение** скрипта до того момента, когда:\n * Весь HTML-документ будет полностью распарсен (**DOM готов**).\n * Событие `DOMContentLoaded` вот-вот произойдет.\n\n**Ключевое преимущество `defer`:** скрипты выполняются **строго в том порядке**, в котором они объявлены в HTML, независимо от времени загрузки.\n\n```html\n\n\n\n\n\n```\n\n### Сравнительная таблица `async` vs `defer`\n\n| Критерий | Без атрибутов (обычный) | `async` | `defer` |\n| :--- | :--- | :--- | :--- |\n| **Загрузка (парсинг HTML)** | **Блокируется** | **Не блокируется** (параллельная) | **Не блокируется** (параллельная) |\n| **Выполнение (относительно парсинга)** | Сразу после загрузки, парсинг приостанавливается | Сразу после загрузки, парсинг приостанавливается | После завершения парсинга HTML, перед `DOMContentLoaded` |\n| **Гарантия порядка выполнения** | Да (по очереди загрузки) | **Нет** (кто раньше загрузился) | **Да** (как указано в разметке) |\n| **Зависимость от готовности DOM** | Нет (DOM может быть не готов) | Нет (DOM может быть не готов) | **Да** (DOM гарантированно готов) |\n\n### Почему `defer` часто является лучшим выбором?\n\n* **Предсказуемость:** Порядок выполнения критически важен, когда скрипты зависят друг от друга (например, библиотека -> плагин -> ваш код).\n* **Безопасность DOM:** Поскольку выполнение происходит после построения DOM, вам не нужны обертки вроде `DOMContentLoaded` для доступа к элементам страницы.\n* **Производительность:** Максимально ускоряет отрисовку контента, полностью убирая блокировку парсинга.\n\n### Практический пример и современный подход\n\nВ современном workflow, особенно при использовании сборщиков (Webpack, Vite), скрипты часто вставляются в `` с атрибутом `defer`. Это стало лучшей практикой.\n\n```html\n\n\n\n \n Современная страница\n \n \n\n\n

Контент загружается и отрисовывается без задержек

\n \n\n\n```\n\n**Важное замечание:** Атрибут `defer` работает **только для внешних скриптов** (с атрибутом `src`). Для inline-скриптов он не имеет эффекта.\n\n### Итог\n\nИспользуйте **`defer`** для большинства скриптов, которые взаимодействуют с DOM или зависят друг от друга. Используйте **`async`** для полностью изолированных сторонних скриптов, где порядок и момент выполнения не важны. Отказ от блокирующих скриптов — один из самых простых и эффективных шагов в оптимизации скорости загрузки веб-приложения.","dateCreated":"2026-04-06T23:22:29.372035","upvoteCount":0,"author":{"@type":"Person","name":"deepseek-v3.2"}}}}
← Назад к вопросам

Что такое Defer?

2.3 Middle🔥 151 комментариев
#Другое

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое директивы defer и async в контексте загрузки JavaScript?

В современной веб-разработке defer и async — это булевы атрибуты тега <script>, которые управляют тем, как и когда браузер загружает и выполняет внешние JavaScript-файлы. Они критически важны для оптимизации производительности веб-страниц, так как позволяют избежать блокировки парсинга и отрисовки HTML.

Основная проблема: блокирующий парсинг

По умолчанию, когда браузер встречает тег <script> без атрибутов в процессе парсинга HTML, он приостанавливает построение DOM (Document Object Model), чтобы:

  1. Загрузить скрипт (если он внешний).
  2. Выполнить его содержимое.

Только после этого парсинг HTML возобновляется. Для тяжелых скриптов или медленных сетей это приводит к долгой задержке перед отображением страницы (плохие метрики FCP — First Contentful Paint и LCP — Largest Contentful Paint).

<!-- Классический блокирующий скрипт. Парсинг HTML остановится здесь -->
<script src="heavy-script.js"></script>

Решение: атрибуты async и defer

Оба атрибута заставляют браузер загружать скрипт асинхронно, не останавливая парсинг HTML. Однако они кардинально различаются моментом выполнения.

Атрибут async

Скрипт с async выполняется как только загрузится, при этом парсинг HTML приостанавливается на время его выполнения. Порядок выполнения не гарантирован — какой скрипт загрузится первым, тот и запустится.

<script async src="analytics.js"></script>
<script async src="widget.js"></script>
<!-- widget.js может выполниться ДО analytics.js, если загрузится быстрее -->

Идеальное применение: для абсолютно независимых скриптов, например, аналитики, рекламных баннеров, виджетов соцсетей, которые не зависят от DOM или других скриптов.

Атрибут defer — подробный разбор

defer — это более предсказуемый и безопасный вариант. Он указывает браузеру:

  1. Загружать скрипт немедленно, в фоновом режиме, параллельно с парсингом HTML.
  2. Отложить выполнение скрипта до того момента, когда:
    * Весь HTML-документ будет полностью распарсен (**DOM готов**).
    * Событие `DOMContentLoaded` вот-вот произойдет.

Ключевое преимущество defer: скрипты выполняются строго в том порядке, в котором они объявлены в HTML, независимо от времени загрузки.

<!-- Парсинг HTML НЕ блокируется. Скрипты загружаются параллельно. -->
<script defer src="vendor-library.js"></script>
<script defer src="app-logic.js"></script>
<script defer src="ui-components.js"></script>
<!-- Гарантированный порядок выполнения: 1. library.js, 2. app-logic.js, 3. ui-components.js -->

Сравнительная таблица async vs defer

КритерийБез атрибутов (обычный)asyncdefer
Загрузка (парсинг HTML)БлокируетсяНе блокируется (параллельная)Не блокируется (параллельная)
Выполнение (относительно парсинга)Сразу после загрузки, парсинг приостанавливаетсяСразу после загрузки, парсинг приостанавливаетсяПосле завершения парсинга HTML, перед DOMContentLoaded
Гарантия порядка выполненияДа (по очереди загрузки)Нет (кто раньше загрузился)Да (как указано в разметке)
Зависимость от готовности DOMНет (DOM может быть не готов)Нет (DOM может быть не готов)Да (DOM гарантированно готов)

Почему defer часто является лучшим выбором?

  • Предсказуемость: Порядок выполнения критически важен, когда скрипты зависят друг от друга (например, библиотека -> плагин -> ваш код).
  • Безопасность DOM: Поскольку выполнение происходит после построения DOM, вам не нужны обертки вроде DOMContentLoaded для доступа к элементам страницы.
  • Производительность: Максимально ускоряет отрисовку контента, полностью убирая блокировку парсинга.

Практический пример и современный подход

В современном workflow, особенно при использовании сборщиков (Webpack, Vite), скрипты часто вставляются в <head> с атрибутом defer. Это стало лучшей практикой.

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Современная страница</title>
    <!-- Скрипты в head с defer — это нормально и правильно! -->
    <script defer src="bundle.js"></script>
</head>
<body>
    <h1>Контент загружается и отрисовывается без задержек</h1>
    <!-- К моменту выполнения bundle.js весь этот DOM уже будет готов -->
</body>
</html>

Важное замечание: Атрибут defer работает только для внешних скриптов (с атрибутом src). Для inline-скриптов он не имеет эффекта.

Итог

Используйте defer для большинства скриптов, которые взаимодействуют с DOM или зависят друг от друга. Используйте async для полностью изолированных сторонних скриптов, где порядок и момент выполнения не важны. Отказ от блокирующих скриптов — один из самых простых и эффективных шагов в оптимизации скорости загрузки веб-приложения.