CSS-in-JS
警告:目前服务器组件不支持需要运行时 JavaScript 的 CSS-in-JS 库。使用 CSS-in-JS 和更新的 React 功能(如服务器组件和流式传输)需要库作者支持最新版本的 React,包括并发渲染。
我们正在与 React 团队合作开发上游 API,以处理 CSS 和 JavaScript 资产,并支持 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@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 功能来确定样式注入的位置。- 在流式传输期间,每个块的样式将被收集并附加到现有样式中。客户端水合完成后,
styled-components
将像往常一样接管并注入任何进一步的动态样式。- 我们特别在树的顶层使用客户端组件作为样式注册表,因为以这种方式提取 CSS 规则更有效率。它避免了在后续的服务器渲染中重新生成样式,并防止它们发送到服务器组件有效负载中。
- 对于需要配置 styled-components 编译的单个属性的高级用例,你可以阅读我们的Next.js styled-components API 参考以了解更多信息。
这篇文章对您有帮助吗?