Какие ограничения клиентских компонентов важно учитывать и как они влияют на решение?
Компоненты
Клиентские компоненты ('use client') дают интерактивность, но за неё платят: их код едет в браузер и должен пережить гидратацию.
Ограничения
Код попадает в бандл. Каждый клиентский компонент и всё, что он импортирует, увеличивают JS, который пользователь качает и парсит. Тяжёлая зависимость (markdown-парсер, date-библиотека), затянутая в клиентский компонент, — прямой удар по загрузке.
Граница заразительна. Всё, что импортируется из клиентского модуля, становится клиентским. Поэтому 'use client' ставят как можно ниже по дереву — на листья-острова, а не на страницу.
Нет прямого доступа к серверным ресурсам: ни БД, ни файловой системы, ни секретов (env без NEXT_PUBLIC). Только через API/Server Actions.
Гидратация. Первый клиентский рендер обязан совпасть с серверным HTML, иначе hydration mismatch. Отсюда запреты: Date.now()/random в рендере, чтение window/localStorage в теле компонента (только в useEffect), локале-зависимое форматирование без фиксации.
Данные — асинхронно. Клиентский компонент не может быть async-функцией: данные — через хуки (React Query, use(promise)) с состояниями загрузки.
Пропсы от серверных компонентов должны быть сериализуемыми: функции (кроме Server Actions), инстансы классов, незарегистрированные Symbol передать нельзя — только сериализуемые значения (и Server Actions).
Как это влияет на решение
Проектировать «острова»: серверный компонент грузит данные и рендерит разметку, клиентский — только интерактивная часть (кнопка, форма, слайдер). Тяжёлые библиотеки держать на сервере или лениво импортировать в клиенте.
Коротко для собеседования
Клиентские компоненты: их код (и импорты) попадают в бандл, граница 'use client' заразительна — ставить как можно ниже; нет доступа к БД/секретам; обязательное совпадение с серверным HTML при гидратации (никаких Date.now/window в рендере); не могут быть async; принимают только сериализуемые пропсы. Отсюда архитектура островов.