Как браузер загружает страницу: базовая картина
Когда пользователь открывает страницу, браузер выполняет несколько этапов:
- Загружает HTML
- Парсит HTML и строит DOM
- Загружает внешние ресурсы (CSS, JS, изображения, шрифты)
- Исполняет JavaScript
- Рисует страницу (render)
- Сообщает о готовности через события (events)
Важно: эти процессы частично параллельны, но JavaScript способен блокировать парсер — отсюда все тонкости.
События жизненного цикла страницы
DOMContentLoaded
Событие срабатывает, когда:
- HTML полностью загружен
- DOM полностью построен. Но изображения, шрифты и другие ресурсы могут ещё загружаться.
Когда использовать
- Инициализация UI
- Навешивание обработчиков
- Работа с DOM-элементами
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM готов');
});
Это самое популярное и безопасное событие для старта логики интерфейса.
load
Срабатывает, когда:
- DOM готов
- Все ресурсы страницы полностью загружены (images, css, iframe и т.д.)
window.addEventListener('load', () => {
console.log('Страница и все ресурсы загружены');
});
Когда использовать
- Работа с размерами изображений
- Ленивая инициализация тяжёлых виджетов
- Метрики реального рендера
beforeunload
Срабатывает перед тем, как пользователь покинет страницу.
Типичные кейсы
- Предупреждение о несохранённых данных
- Завершение пользовательской сессии
unload
Срабатывает в момент выгрузки страницы.
window.addEventListener('unload', () => {
console.log('Страница выгружается');
});
Ограничения:
- Асинхронные операции (fetch, setTimeout) не гарантированы
- Не использовать для аналитики
Скрипты: async и defer
Обычный <script>
<script src="app.js"></script>
- HTML-парсер останавливается
- Скрипт загружается и сразу выполняется
- Блокирует рендер
defer
<script src="app.js" defer></script>
- Загружается параллельно HTML
- Выполняется после построения DOM
- Порядок скриптов сохраняется
- DOMContentLoaded ждёт выполнения defer-скриптов
Лучший выбор для большинства приложений
async
<script src="analytics.js" async></script>
- Загружается параллельно
- Выполняется сразу после загрузки
- Порядок выполнения не гарантирован
- Не блокирует HTML
Используется для
- Аналитики
- Рекламы
- Независимых скриптов
Загрузка ресурсов: onload и onerror
onload
Срабатывает, когда конкретный ресурс успешно загружен.
const img = new Image();
img.src = '/photo.jpg';
img.onload = () => {
console.log('Изображение загружено');
};
Работает для:
- <img>
- <script>
- <link>
- <iframe>
onerror
Срабатывает при ошибке загрузки.
img.onerror = () => {
console.log('Ошибка загрузки изображения');
};
Типичные сценарии
- Фолбэк-изображения
- Повторная загрузка
- Логирование ошибок CDN
Как всё это связано между собой
Последовательность в реальной жизни выглядит примерно так:
- HTML начинает парситься
- defer и async скрипты загружаются
- DOM построен → DOMContentLoaded
- defer-скрипты выполнены
- Загружены все ресурсы → load
- Пользователь закрывает вкладку → beforeunload → unload