Chakra UI — это современная библиотека компонентов для React, ориентированная на удобство разработки интерфейсов с поддержкой темы, адаптивности и доступности. Однако при интеграции с серверным рендерингом (SSR, Server-Side Rendering) возникают специфические проблемы, которые требуют тщательного понимания механизма работы Chakra UI и особенностей SSR.
Chakra UI использует CSS-in-JS, что означает динамическую генерацию стилей на основе пропсов компонентов и текущей темы. При серверной отрисовке это создает два основных вызова:
Основная проблема здесь заключается в том, что CSS, сгенерированный на сервере, должен совпадать с CSS на клиенте. Любое расхождение приведет к «мерцающим» стилям или предупреждениям React о несоответствии содержимого DOM.
Отсутствие ChakraProvider на
сервере Если ChakraProvider не используется на
этапе серверного рендеринга, компоненты Chakra не смогут получить
текущую тему и стили. Это приведет к дефолтному отображению или
некорректным стилям.
Использование window или
document на сервере Некоторые компоненты, например
модальные окна или popover, зависят от размеров окна или портала в DOM.
На сервере объектов window и document нет, что
вызывает ошибки выполнения.
Несинхронизированные стили при гидратации Эмоциональная библиотека (Emotion), используемая Chakra UI, генерирует уникальные классы CSS. Если порядок генерации отличается между сервером и клиентом, появляются mismatch warnings в React.
ChakraProvider с темойНа сервере и клиенте необходимо оборачивать приложение в один и тот
же ChakraProvider:
import { ChakraProvider } from "@chakra-ui/react";
import theme from "./theme";
function App({ Component, pageProps }) {
return (
<ChakraProvider theme={theme}>
<Component {...pageProps} />
</ChakraProvider>
);
}
export default App;
Для Next.js это обычно делается в _app.js или
_app.tsx.
Chakra UI использует Emotion для CSS-in-JS, поэтому при SSR нужно извлекать стили, чтобы они попадали в HTML:
import { renderToString } from "react-dom/server";
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";
import { ChakraProvider } from "@chakra-ui/react";
import theme from "./theme";
const cache = createCache({ key: "css" });
const html = renderToString(
<CacheProvider value={cache}>
<ChakraProvider theme={theme}>
<App />
</ChakraProvider>
</CacheProvider>
);
const css = cache.sheet.tags.map(tag => tag.textContent).join("");
Эта техника позволяет вставлять CSS прямо в
<head> HTML, предотвращая мерцание
стилей.
Компоненты, использующие порталы или измерения элементов, нужно
рендерить только на клиенте. Chakra UI предоставляет
useDisclosure и Portal, но для SSR важно
проверять typeof window !== "undefined":
const isClient = typeof window !== "undefined";
return isClient ? <Modal isOpen={isOpen} onCl ose={onClose}>...</Modal> : null;
Такой подход предотвращает ошибки при серверной отрисовке.
Chakra UI поддерживает цветовую схему
(colorMode). Если на сервере и клиенте она отличается,
компонент может «мигнуть» при гидратации. Для согласованности
используют:
ColorModeScript в Next.js
_document.js:import { ColorModeScript } from "@chakra-ui/react";
import theme from "./theme";
<Html>
<Head />
<body>
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
<Main />
<NextScript />
</body>
</Html>
Это гарантирует, что начальная цветовая схема совпадает на сервере и клиенте.
ChakraProvider с
темой на сервере и клиенте.ColorModeScript для согласования цветовой
схемы.CacheProvider Emotion для
SSR-совместимости.window, document и
другим браузерным API на сервере.Соблюдение этих принципов позволяет Chakra UI корректно работать с серверным рендерингом, избегая расхождений стилей, ошибок гидратации и мерцания интерфейса.