CSS-in-JS
警告: 将 CSS-in-JS 与较新的 React 功能(如服务器组件和流式处理)结合使用,需要库作者支持最新版本的 React,包括 并发渲染。
以下库在 app 目录中的客户端组件中受支持(按字母顺序排列)
- ant-design
- chakra-ui
- @fluentui/react-components
- kuma-ui
- @mui/material
- @mui/joy
- pandacss
- styled-jsx
- styled-components
- stylex
- tamagui
- tss-react
- vanilla-extract
以下库目前正在努力提供支持
须知:我们正在测试不同的 CSS-in-JS 库,并将为支持 React 18 功能和/或
app目录的库添加更多示例。
如果您想为服务器组件设置样式,我们建议使用 CSS 模块 或其他输出 CSS 文件的解决方案,例如 PostCSS 或 Tailwind CSS。
在 app 中配置 CSS-in-JS
配置 CSS-in-JS 是一个三步选择加入过程,包括
- 一个样式注册表,用于收集渲染中的所有 CSS 规则。
- 新的 useServerInsertedHTML钩子,用于在任何可能使用它们的内容之前注入规则。
- 一个客户端组件,在初始服务器端渲染期间使用样式注册表包装你的应用。
styled-jsx
在客户端组件中使用 styled-jsx 需要使用 v5.1.0。首先,创建一个新的注册表
app/registry.tsx
'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
}) {
  // Only create stylesheet once with lazy initial state
  // x-ref: https://reactjs.ac.cn/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>
}然后,使用注册表包装你的 根布局
app/layout.tsx
import StyledJsxRegistry from './registry'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledJsxRegistry>{children}</StyledJsxRegistry>
      </body>
    </html>
  )
}Styled Components
以下是如何配置 styled-components@6 或更高版本的示例
首先,在 next.config.js 中启用 styled-components。
next.config.js
module.exports = {
  compiler: {
    styledComponents: true,
  },
}然后,使用 styled-components API 创建一个全局注册表组件,以收集渲染期间生成的所有 CSS 样式规则,以及一个返回这些规则的函数。然后使用 useServerInsertedHTML 钩子将注册表中收集的样式注入到根布局的 <head> HTML 标签中。
lib/registry.tsx
'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
}) {
  // Only create stylesheet once with lazy initial state
  // x-ref: https://reactjs.ac.cn/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
app/layout.tsx
import StyledComponentsRegistry from './lib/registry'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}须知:
- 在服务器渲染期间,样式将被提取到全局注册表并刷新到 HTML 的
<head>中。这确保了样式规则放置在任何可能使用它们的内容之前。将来,我们可能会使用即将推出的 React 功能来确定在何处注入样式。- 在流式处理期间,来自每个块的样式将被收集并附加到现有样式。在客户端 hydration 完成后,
styled-components将像往常一样接管并注入任何进一步的动态样式。- 我们专门在树的顶层使用客户端组件作为样式注册表,因为以这种方式提取 CSS 规则更有效。它可以避免在后续服务器渲染时重新生成样式,并防止它们在服务器组件有效负载中发送。
- 对于需要配置 styled-components 编译的各个属性的高级用例,您可以阅读我们的 Next.js styled-components API 参考 以了解更多信息。
这有帮助吗?