CSS-in-JS

Avertissement : Les bibliothèques CSS-in-JS qui nécessitent du JavaScript côté client ne sont actuellement pas prises en charge dans les composants serveur. L'utilisation de CSS-in-JS avec les nouvelles fonctionnalités de React comme les composants serveur et le streaming nécessite que les auteurs de bibliothèques prennent en charge la dernière version de React, y compris le rendu concurrent.

Nous travaillons avec l'équipe React sur des APIs en amont pour gérer les assets CSS et JavaScript avec prise en charge des composants serveur React et de l'architecture de streaming.

Les bibliothèques suivantes sont prises en charge dans les composants client du répertoire app (par ordre alphabétique) :

Les bibliothèques suivantes travaillent actuellement à la prise en charge :

Bon à savoir : Nous testons différentes bibliothèques CSS-in-JS et nous ajouterons plus d'exemples pour les bibliothèques qui prennent en charge les fonctionnalités de React 18 et/ou le répertoire app.

Si vous souhaitez styliser des composants serveur, nous recommandons d'utiliser les modules CSS ou d'autres solutions qui génèrent des fichiers CSS, comme PostCSS ou Tailwind CSS.

Configurer CSS-in-JS dans app

La configuration de CSS-in-JS est un processus en trois étapes qui nécessite :

  1. Un registre de styles pour collecter toutes les règles CSS lors d'un rendu.
  2. Le nouveau hook useServerInsertedHTML pour injecter les règles avant tout contenu qui pourrait les utiliser.
  3. Un composant client qui encapsule votre application avec le registre de styles pendant le rendu côté serveur initial.

styled-jsx

L'utilisation de styled-jsx dans les composants client nécessite la version v5.1.0. D'abord, créez un nouveau registre :

'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
}) {
  // Crée la feuille de style une seule fois avec un état initial paresseux
  // 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 }) {
  // Crée la feuille de style une seule fois avec un état initial paresseux
  // 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>
}

Ensuite, encapsulez votre layout racine avec le registre :

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

Voir un exemple ici.

Styled Components

Voici un exemple de configuration pour styled-components@6 ou plus récent :

D'abord, utilisez l'API styled-components pour créer un composant de registre global afin de collecter toutes les règles de style CSS générées pendant un rendu, et une fonction pour retourner ces règles. Ensuite, utilisez le hook useServerInsertedHTML pour injecter les styles collectés dans le registre dans la balise <head> HTML du layout racine.

'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
}) {
  // Crée la feuille de style une seule fois avec un état initial paresseux
  // 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 }) {
  // Crée la feuille de style une seule fois avec un état initial paresseux
  // 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>
  )
}

Encapsulez les children du layout racine avec le composant de registre de styles :

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

Voir un exemple ici.

Bon à savoir :

  • Pendant le rendu côté serveur, les styles seront extraits vers un registre global et injectés dans le <head> de votre HTML. Cela garantit que les règles de style sont placées avant tout contenu qui pourrait les utiliser. À l'avenir, nous pourrions utiliser une future fonctionnalité de React pour déterminer où injecter les styles.
  • Pendant le streaming, les styles de chaque morceau seront collectés et ajoutés aux styles existants. Après l'hydratation côté client, styled-components prendra le relais comme d'habitude et injectera tout style dynamique supplémentaire.
  • Nous utilisons spécifiquement un composant client au niveau supérieur de l'arbre pour le registre de styles car c'est plus efficace pour extraire les règles CSS de cette manière. Cela évite de regénérer les styles lors des rendus serveur suivants, et empêche leur envoi dans le payload des composants serveur.