Найти в Дзене
Программист - турист

Подготовка к собеседованию frontend (тонкости подключения стилей и скриптов)

CSS почти всегда рендер-блокирующий → кладём в <head>, оптимизируем через critical CSS + preload/media. Скрипты по умолчанию парсер-блокируют → используем defer, а для модулей — type="module" (они «деферятся» сами). Для CDN — SRI + crossorigin. Шрифты — preload + font-display. Следим за порядком подключений, кэшем и CORS. Ниже — все тонкости с проверенными приёмами и ловушками Пример «чистого» подключения (html): Critical CSS inline, остальное — отложить: Альтернативные темы:
Можно подключать несколько таблиц и переключать их в рантайме: <link rel="preload" href="/fonts/Inter.var.woff2" as="font" type="font/woff2" crossorigin> CORS обязателен для кросс-доменных шрифтов (crossorigin="anonymous" на <link> и корректные заголовки на сервере). В @font-face укажите font-display: swap|optional — устранит FOIT. Если шрифт с CDN — добавьте preconnect: <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> Классические скрипты: ES-модули (type="module"): Preload модулей (ускорение
Оглавление
CSS почти всегда рендер-блокирующий → кладём в <head>, оптимизируем через critical CSS + preload/media. Скрипты по умолчанию парсер-блокируют → используем defer, а для модулей — type="module" (они «деферятся» сами). Для CDN — SRI + crossorigin. Шрифты — preload + font-display. Следим за порядком подключений, кэшем и CORS. Ниже — все тонкости с проверенными приёмами и ловушками

CSS: базовые правила и порядок

  • Рендер-блокирующий характер. Любой <link rel="stylesheet"> в <head> задержит отрисовку до загрузки/парсинга файла. Это нормально для критичных стилей.
  • Порядок имеет значение. Поздние файлы переопределяют ранние (каскад). Расставляйте базу → компоненты → утилиты/оверрайды. Для явного контроля используйте @ layer
  • Избегайте @import в продакшене. Он добавляет лишние блокирующие запросы. Предпочтительнее отдельные <link>.

Пример «чистого» подключения (html):

Отложенная и условная загрузка CSS

Critical CSS inline, остальное — отложить:

-2
  • Важно: as="style" обязателен, иначе возможна двойная загрузка.
  • Условные стили через media:
    media="(min-width: 768px)" или media="print" делают загрузку не-блокирующей для первичного рендера.
-3

Альтернативные темы:
Можно подключать несколько таблиц и переключать их в рантайме:

-4

Шрифты: скорость и отсутствие «моргания»

<link rel="preload" href="/fonts/Inter.var.woff2" as="font" type="font/woff2" crossorigin>

CORS обязателен для кросс-доменных шрифтов (crossorigin="anonymous" на <link> и корректные заголовки на сервере).

В @font-face укажите font-display: swap|optional — устранит FOIT.

Если шрифт с CDN — добавьте preconnect:

<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

Скрипты: блокировка, порядок, модули

-5

Классические скрипты:

  • defer — скачиваются параллельно, выполняются после парсинга и в порядке вхождения
  • async — скачиваются параллельно, выполняются по готовности (порядок не гарантирован). Хорошо для независимой аналитики
  • Инлайновый <script> игнорирует async/defer

ES-модули (type="module"):

  • По умолчанию как defer: выполняются после парсинга, загрузка по графу импортов.
  • Поддерживают import/export, import() и top-level await.
  • Требуют CORS для кросс-доменных модулей и корректный MIME.
-6

Preload модулей (ускорение «первого байта» для графа импортов):

<link rel="modulepreload" href="/js/main.js">
<script type="module" src="/js/main.js"></script>

Безопасность: SRI, CSP, CORS, referrer

Subresource Integrity (SRI) для CDN:

-7

Подводные камни и редкие нюансы

  • Двойная загрузка при preload: атрибуты as/crossorigin должны совпадать с будущим <link rel="stylesheet"> / <script>, иначе браузер скачает ещё раз.
  • События загрузки: link.onload/onerror и window.addEventListener('error', …, true) помогают ловить сбои ресурсов.
  • Много мелких файлов не всегда хорошо. HTTP/2/3 помогает, но сверхдробление увеличивает задержки из-за латентности и приоритизации. Компонентная сборка + разумный code-splitting — оптимальный путь.
  • Шрифты без CORS часто «тихо» не применяются (особенно с CDN). Всегда проверяйте заголовки на источнике.
  • @import внутри CSS (особенно из runtime-генерируемых файлов) — частая причина скрытых блокировок и «ступеньки» CLS, избегайте.

Рецепт «эталонного» <head>

-8