CSS-in-JS

Warnung: CSS-in-JS-Bibliotheken, die Laufzeit-JavaScript benötigen, werden derzeit in Server Components nicht unterstützt. Die Verwendung von CSS-in-JS mit neueren React-Funktionen wie Server Components und Streaming erfordert, dass Bibliotheksautoren die neueste Version von React unterstützen, einschließlich Concurrent Rendering.

Wir arbeiten mit dem React-Team an Upstream-APIs, um CSS- und JavaScript-Assets mit Unterstützung für React Server Components und Streaming-Architektur zu handhaben.

Die folgenden Bibliotheken werden in Client Components im app-Verzeichnis unterstützt (alphabetisch):

Die folgenden Bibliotheken arbeiten derzeit an der Unterstützung:

Gut zu wissen: Wir testen verschiedene CSS-in-JS-Bibliotheken und werden weitere Beispiele für Bibliotheken hinzufügen, die React 18-Funktionen und/oder das app-Verzeichnis unterstützen.

Wenn Sie Server Components gestalten möchten, empfehlen wir die Verwendung von CSS Modules oder anderen Lösungen, die CSS-Dateien ausgeben, wie PostCSS oder Tailwind CSS.

Konfiguration von CSS-in-JS in app

Die Konfiguration von CSS-in-JS ist ein dreistufiger Opt-in-Prozess, der Folgendes umfasst:

  1. Ein Style-Registry, um alle CSS-Regeln während eines Renders zu sammeln.
  2. Den neuen useServerInsertedHTML-Hook, um Regeln vor jeglichem Injektion einzufügen, der sie verwenden könnte.
  3. Eine Client Component, die Ihre App während des initialen Server-Side-Renderings mit der Style-Registry umschließt.

styled-jsx

Die Verwendung von styled-jsx in Client Components erfordert Version v5.1.0. Erstellen Sie zunächst eine neue Registry:

'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
}) {
  // Stylesheet nur einmal mit lazy initial state erstellen
  // 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 }) {
  // Stylesheet nur einmal mit lazy initial state erstellen
  // 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>
}

Dann umschließen Sie Ihr Root Layout mit der Registry:

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>
  )
}

Beispiel hier ansehen.

Styled Components

Nachfolgend ein Beispiel für die Konfiguration von styled-components@6 oder neuer:

Aktivieren Sie zunächst styled-components in next.config.js.

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

Verwenden Sie dann die styled-components-API, um eine globale Registry-Komponente zu erstellen, die alle während eines Renders generierten CSS-Style-Regeln sammelt, sowie eine Funktion, um diese Regeln zurückzugeben. Verwenden Sie dann den useServerInsertedHTML-Hook, um die in der Registry gesammelten Styles in das <head>-HTML-Tag im Root-Layout einzufügen.

'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
}) {
  // Stylesheet nur einmal mit lazy initial state erstellen
  // 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 }) {
  // Stylesheet nur einmal mit lazy initial state erstellen
  // 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>
  )
}

Umschließen Sie die children des Root-Layouts mit der Style-Registry-Komponente:

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>
  )
}

Beispiel hier ansehen.

Gut zu wissen:

  • Während des Server-Renderings werden Styles in eine globale Registry extrahiert und in den <head> Ihres HTML eingefügt. Dadurch wird sichergestellt, dass die Style-Regeln vor jeglichem Inhalt platziert werden, der sie verwenden könnte. In Zukunft könnten wir eine kommende React-Funktion verwenden, um zu bestimmen, wo die Styles eingefügt werden sollen.
  • Während des Streamings werden Styles aus jedem Chunk gesammelt und an bestehende Styles angehängt. Nachdem das Client-Side-Hydration abgeschlossen ist, übernimmt styled-components wie gewohnt und fügt weitere dynamische Styles ein.
  • Wir verwenden speziell eine Client Component auf der obersten Ebene des Baums für die Style-Registry, da dies effizienter ist, um CSS-Regeln zu extrahieren. Es vermeidet die Neugenerierung von Styles bei nachfolgenden Server-Rendern und verhindert, dass sie im Server-Component-Payload gesendet werden.
  • Für fortgeschrittene Anwendungsfälle, in denen Sie individuelle Eigenschaften der styled-components-Kompilierung konfigurieren müssen, können Sie unsere Next.js styled-components API-Referenz lesen, um mehr zu erfahren.