Вопрос проверяет понимание критического пути рендеринга браузера и того, какие HTML-теги и их атрибуты влияют на скорость появления страницы.
Рендеринг блокируют <script> без атрибутов и <link rel="stylesheet">. Браузер останавливает построение DOM, пока не загрузит и не выполнит скрипт или не применит стили. В React-приложениях эта тема важна при настройке index.html, SSR/SSG и lazy loading.
Браузер строит DOM последовательно, сверху вниз. Если он встречает тег, который требует загрузки или выполнения ресурса — он останавливается и ждёт. Страница не отображается до тех пор, пока этот ресурс не будет обработан.
<script> — блокирует парсинг DOM<!-- ❌ Блокирует: браузер остановит парсинг, пока не загрузит и не выполнит -->
<script src="app.js"></script>
<!-- ✅ async: загружает параллельно, выполняет сразу после загрузки -->
<script src="app.js" async></script>
<!-- ✅ defer: загружает параллельно, выполняет после полного парсинга DOM -->
<script src="app.js" defer></script>Разница между async и defer:
async — выполняется в момент загрузки, порядок не гарантирован
defer — выполняется после парсинга, в порядке объявления
React-приложения (CRA, Vite) по умолчанию добавляют defer к бандлу.
<link rel="stylesheet"> — блокирует рендеринг<!-- ❌ Блокирует: браузер не нарисует ни одного пикселя без CSS -->
<link rel="stylesheet" href="styles.css">
<!-- ✅ Загрузка некритического CSS без блокировки -->
<link rel="stylesheet" href="print.css" media="print">
<link rel="stylesheet" href="heavy.css" media="(min-width: 1200px)">CSS блокирует рендеринг, потому что браузер должен построить CSSOM до отрисовки — иначе страница «мигнет» без стилей (FOUC).
<!-- Изображения — не блокируют, грузятся параллельно -->
<img src="photo.jpg">
<!-- Шрифты через font-face — не блокируют парсинг, но могут вызвать FOIT -->
<link rel="preload" href="font.woff2" as="font" crossorigin>
<!-- preload/prefetch — только подсказки браузеру, не блокируют -->
<link rel="preload" href="chunk.js" as="script">
<link rel="prefetch" href="next-page.js"><head>
<!-- ❌ Блокирующий CSS — нормально для критических стилей -->
<link rel="stylesheet" href="critical.css">
<!-- ✅ Некритический CSS — асинхронная загрузка через трюк с onload -->
<link rel="preload" href="non-critical.css" as="style"
onload="this.rel='stylesheet'">
</head>
<body>
<!-- контент -->
<!-- ✅ Скрипты в конце body или с defer — DOM уже построен -->
<script src="app.js" defer></script>
</body>В React напрямую с этими тегами работают редко, но тема всплывает в нескольких контекстах:
// Code splitting — Webpack/Vite добавят defer автоматически
const LazyPage = React.lazy(() => import('./Page'));
// Next.js — встроенное управление критическим CSS
// Стили компонентов инлайнятся в <head>, остальное — defer
// Vite/CRA index.html — бандл всегда идёт с defer
// <script type="module" src="/src/main.jsx"></script>
// type="module" ведёт себя как defer по умолчаниюFrontend developer
Ментор по Frontend
Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства
Записаться на консультацию