CSS-in-JS

Avertissement : Les bibliothèques CSS-in-JS nécessitant un runtime JavaScript 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 clients du répertoire app (par ordre alphabétique) :

Les bibliothèques suivantes travaillent actuellement sur leur prise en charge :

Bon à savoir : Nous testons différentes bibliothèques CSS-in-JS et nous ajouterons plus d'exemples pour les bibliothèques prenant 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 produisant 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 nécessitant une activation explicite :

  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 lors du rendu initial côté serveur.

styled-jsx

L'utilisation de styled-jsx dans les composants clients 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
}) {
  // Ne crée la feuille de style qu'une fois avec un état initial paresseux
  // réf : 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 }) {
  // Ne crée la feuille de style qu'une fois avec un état initial paresseux
  // réf : 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 supérieur :

D'abord, activez styled-components dans next.config.js.

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

Ensuite, 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 lors d'un rendu, et une fonction pour retourner ces règles. Puis 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
}) {
  // Ne crée la feuille de style qu'une fois avec un état initial paresseux
  // réf : 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 }) {
  // Ne crée la feuille de style qu'une fois avec un état initial paresseux
  // réf : 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. Cela évite de régénérer les styles lors des rendus serveur suivants et empêche leur envoi dans le payload des composants serveur.
  • Pour les cas d'utilisation avancés où vous devez configurer des propriétés individuelles de la compilation styled-components, vous pouvez consulter notre référence API Next.js pour styled-components pour en savoir plus.