Использование CSS-in-JS библиотек

Предупреждение: Использование CSS-in-JS с новыми функциями React, такими как Серверные Компоненты и Потоковая передача, требует от авторов библиотек поддержки последней версии React, включая конкурентный рендеринг.

Следующие библиотеки поддерживаются в Клиентских Компонентах в директории app (в алфавитном порядке):

Следующие библиотеки в настоящее время работают над поддержкой:

Полезно знать: Мы тестируем различные CSS-in-JS библиотеки и будем добавлять больше примеров для библиотек, поддерживающих функции React 18 и/или директорию app.

Настройка CSS-in-JS в app

Настройка CSS-in-JS состоит из трех шагов:

  1. Реестр стилей для сбора всех CSS-правил во время рендеринга.
  2. Новый хук useServerInsertedHTML для вставки правил перед любым контентом, который может их использовать.
  3. Клиентский компонент, который оборачивает ваше приложение с реестром стилей во время первоначального серверного рендеринга.

styled-jsx

Для использования styled-jsx в Клиентских Компонентах требуется версия v5.1.0. Сначала создайте новый реестр:

'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'

export default function StyledJsxRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // Создаем таблицу стилей только один раз с ленивым начальным состоянием
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [jsxStyleRegistry] = useState(() => createStyleRegistry())

  useServerInsertedHTML(() => {
    const styles = jsxStyleRegistry.styles()
    jsxStyleRegistry.flush()
    return <>{styles}</>
  })

  return <StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
}
'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'

export default function StyledJsxRegistry({ children }) {
  // Создаем таблицу стилей только один раз с ленивым начальным состоянием
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [jsxStyleRegistry] = useState(() => createStyleRegistry())

  useServerInsertedHTML(() => {
    const styles = jsxStyleRegistry.styles()
    jsxStyleRegistry.flush()
    return <>{styles}</>
  })

  return <StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
}

Затем оберните ваш корневой макет реестром:

import StyledJsxRegistry from './registry'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledJsxRegistry>{children}</StyledJsxRegistry>
      </body>
    </html>
  )
}
import StyledJsxRegistry from './registry'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <StyledJsxRegistry>{children}</StyledJsxRegistry>
      </body>
    </html>
  )
}

Посмотреть пример здесь.

Styled Components

Ниже приведен пример настройки styled-components@6 или новее:

Сначала включите styled-components в next.config.js.

next.config.js
module.exports = {
  compiler: {
    styledComponents: true,
  },
}

Затем используйте API styled-components для создания глобального компонента реестра, который собирает все CSS-правила, сгенерированные во время рендеринга, и функцию для возврата этих правил. Затем используйте хук useServerInsertedHTML для вставки собранных стилей из реестра в тег <head> HTML в корневом макете.

'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'

export default function StyledComponentsRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // Создаем таблицу стилей только один раз с ленивым начальным состоянием
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())

  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement()
    styledComponentsStyleSheet.instance.clearTag()
    return <>{styles}</>
  })

  if (typeof window !== 'undefined') return <>{children}</>

  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  )
}
'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'

export default function StyledComponentsRegistry({ children }) {
  // Создаем таблицу стилей только один раз с ленивым начальным состоянием
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())

  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement()
    styledComponentsStyleSheet.instance.clearTag()
    return <>{styles}</>
  })

  if (typeof window !== 'undefined') return <>{children}</>

  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  )
}

Оберните children корневого макета компонентом реестра стилей:

import StyledComponentsRegistry from './lib/registry'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}
import StyledComponentsRegistry from './lib/registry'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}

Посмотреть пример здесь.

Полезно знать:

  • Во время серверного рендеринга стили будут извлечены в глобальный реестр и добавлены в <head> вашего HTML. Это гарантирует, что правила стилей будут размещены перед любым контентом, который может их использовать. В будущем мы можем использовать новую функцию React для определения места вставки стилей.
  • Во время потоковой передачи стили из каждого фрагмента будут собираться и добавляться к существующим стилям. После завершения гидратации на стороне клиента styled-components возьмет на себя управление, как обычно, и будет вставлять любые дополнительные динамические стили.
  • Мы специально используем Клиентский Компонент на верхнем уровне дерева для реестра стилей, потому что это более эффективный способ извлечения CSS-правил. Это позволяет избежать повторного генерации стилей при последующих серверных рендерах и предотвращает их отправку в полезной нагрузке Серверного Компонента.
  • Для сложных случаев использования, когда вам нужно настроить отдельные свойства компиляции styled-components, вы можете прочитать нашу справочную документацию по API Next.js для styled-components, чтобы узнать больше.