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) :
kuma-ui
@mui/material
pandacss
styled-jsx
styled-components
style9
tamagui
tss-react
vanilla-extract
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 :
- Un registre de styles pour collecter toutes les règles CSS lors d'un rendu.
- Le nouveau hook
useServerInsertedHTML
pour injecter les règles avant tout contenu qui pourrait les utiliser. - 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>
)
}
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>
)
}
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.