Отказ от CSS в JS во время выполнения: серверные компоненты и стили на этапе сборки
Почему использование CSS-in-JS во время выполнения конфликтует с React Server Components и целями по повышению производительности, как сравниваются Tailwind, CSS Modules и библиотеки без выполнения кода во время работы, и как осуществить безопасную миграцию.
Источники: Why CSS-in-JS Is Dying in 2026: Performance, Server Components, and What to Use Instead
В течение нескольких лет библиотеки CSS-in-JS во время выполнения, такие как styled-components и Emotion, были основным способом стилизации компонентов React: стили ограничивались конкретным компонентом, значения задавались через пропсы, и не возникало конфликтов глобальных имён классов. С тех пор экосистема сместилась в сторону стилей, генерируемых на этапе сборки, что во многом обусловлено требованиями к производительности и появлением React Server Components. В этой статье объясняется, что изменилось, сравниваются основные альтернативы, и приводится практическое правило относительно того, когда следует мигрировать существующую кодовую базу, а когда можно оставить всё как есть.
Многие команды, как крупные, так и небольшие, уже перешли на стилизацию без использования библиотек во время выполнения, и эти причины имеют большое значение перед тем, как выбрать подход.
Затраты на генерацию стилей в браузере
Библиотеки CSS-in-JS, работающие во время выполнения приложения, генерируют CSS в процессе его работы. По мере отрисовки компонентов библиотека преобразует определения стилей (включая значения, зависящие от параметров) в правила CSS, формирует имена классов и вставляет теги <style> в документ. Все эти операции выполняются на основном потоке устройства пользователя. Опубликованные тесты, сравнивающие такой подход со статическим CSS, показывают замедление процесса отрисовки на уровне от 20 до 50 процентов; реальное влияние сильно зависит от конкретного приложения, поэтому такие цифры следует рассматривать как сигнал к измерению производительности собственных страниц, а не как универсальный показатель.
Основная проблема связана с архитектурой, а не с ошибкой в какой-либо конкретной библиотеке: вычисление стилей происходит в браузере, а не на этапе сборки. Это означает, что сам движок стилей входит в пакет JavaScript, поэтому браузеру приходится обрабатывать и выполнять больше скриптов перед тем, как страница станет интерактивной, к тому же вставка стилей конкурирует с процессом отрисовки за время обработки.
Почему серверные компоненты выявили эту слабость
React Server Components (RSC) отрисовываются на сервере, а их результаты отправляются в браузер без передачи кода компонентов в виде клиентского JavaScript. Режим CSS-in-JS в рантайме зависит от среды выполнения JavaScript, которая отслеживает и вставляет стили во время отрисовки, а также от контекста React, который не поддерживается серверными компонентами. Это противоречит подходу, основанному на сервере, который используют такие фреймворки, как Next.js App Router.
На практике использование styled-components или Emotion с серверными компонентами означает обозначение стилизованных частей дерева компонентов как клиентских с помощью директивы 'use client', обычно в сочетании с дополнительной настройкой для сбора стилей во время серверной отрисовки. Когда стилизованные примитивы используются повсеместно, значительная часть дерева компонентов оказывается на стороне клиента. Это сводит на нет большинство преимуществ серверных компонентов, а именно сокращение объема JavaScript, отправляемого в браузер, и уменьшение нагрузки на него, всё это ради поддержки работы библиотеки стилей. Для многих команд такой компромисс оказывается невыгодным.
Альтернативы во время сборки
Подход CSS-in-JS во время выполнения достиг своего пика примерно между 2018 и 2023 годами. Сегодня существует несколько зрелых вариантов, позволяющих избежать таких затрат во время выполнения, каждый из которых подходит определенным командам по их предпочтениям.
Tailwind CSS как стандартный выбор
Tailwind CSS стал стандартным выбором для новых проектов на React и Next.js. Вы создаете классы-функции непосредственно в маркапе, а на этапе сборки генерируется только CSS для тех классов, которые действительно используются. Нет необходимости в рантайм-стилизации, размер генерируемого стилевого листа остается маленьким, и поскольку результат — обычный CSS, он работает в серверных компонентах без какой-либо дополнительной обработки.
CSS Modules для команд, предпочитающих обычный CSS
Если вы предпочитаете писать обычный CSS вместо классов-функций, CSS Modules предоставляют имена классов с локальным областью действия без каких-либо затрат в рантайме. Большинство бандлеров и инструментальных цепочек фреймворков поддерживают их из коробки, поэтому для их использования обычно не требуется никакой настройки.
CSS-in-JS без рантайм-затрат для знакомой модели разработки
Библиотеки вроде Panda CSS и Vanilla Extract позволяют продолжать использовать стили в JavaScript или TypeScript, так же как это делалось с styled-components, но они преобразуют всё в статический CSS во время сборки. Вы сохраняете удобство создания стилей и типобезопасность без дополнительной нагрузки во время выполнения, при этом обеспечивается полная совместимость с Server Components. Основное изменение заключается в том, что стили должны быть статически анализируемыми, поэтому значения, которые меняются во время выполнения, обычно выражаются с помощью вариантов или пользовательских свойств CSS, а не произвольных параметров. Шаблоны преобразования значений JavaScript в переменные CSS рассмотрены в нашем руководстве по пользовательским свойствам CSS во время выполнения.
Как решить, когда мигрировать
Новые проекты
Для нового проекта сегодня практически нет причин выбирать решения типа CSS-in-JS с временем выполнения. Разумный стандартный вариант:
- Tailwind CSS для большинства проектов.
- CSS Modules, если команда предпочитает традиционные таблицы стилей.
- Библиотеку CSS-in-JS без времени выполнения, если вы хотите продолжать писать стили на TypeScript, не оплачивая услуги времени выполнения.
Существующие проекты
Если приложение уже построено с использованием styled-components или Emotion, нет необходимости спешить. Обе библиотеки по-прежнему хорошо работают в приложениях с клиентской отрисовкой. Миграция становится целесообразной, когда вы планируете перейти на Server Components или когда анализ производительности показывает, что стилизация составляет значительную часть затрат на отрисовку.
При миграции делайте её поэтапно, по одному компоненту за раз, переходя на Tailwind или CSS Modules. Листовые компоненты и общие примитивы, такие как кнопки, — отличные первоначальные цели для перехода. Оба подхода могут сосуществовать во время переходного периода, но следите за специфичностью и порядком применения стилей, когда старые и новые стили сосуществуют рядом.
Заключение
- CSS-in-JS во время выполнения решал реальные проблемы, но он вычисляет стили на клиенте, что увеличивает размер бандла и занимает время на основной цепи выполнения.
- Server Components делают эту проблему более заметной, поскольку библиотеки зависят от клиентского JavaScript и возвращают стилизованные структуры обратно на клиент.
- Tailwind CSS, CSS Modules и библиотеки без выполнения во время работы, такие как Panda CSS и Vanilla Extract, генерируют статический CSS во время сборки и естественно работают с Server Components.