CSS-in-JS
경고: 런타임 자바스크립트를 요구하는 CSS-in-JS 라이브러리는 현재 Server Components에서 지원되지 않습니다. Server Components와 스트리밍과 같은 최신 React 기능과 CSS-in-JS를 사용하려면 라이브러리 작성자가 동시 렌더링 (opens in a new tab)을 포함한 최신 React 버전을 지원해야 합니다.
우리는 React 팀과 협력하여 React Server Components 및 스트리밍 아키텍처를 지원하는 CSS 및 자바스크립트 자산을 처리하기 위한 업스트림 API를 개발하고 있습니다.
다음 라이브러리는 app
디렉토리의 Client Components에서 지원됩니다 (알파벳순):
ant-design
(opens in a new tab)chakra-ui
(opens in a new tab)@fluentui/react-components
(opens in a new tab)kuma-ui
(opens in a new tab)@mui/material
(opens in a new tab)@mui/joy
(opens in a new tab)pandacss
(opens in a new tab)styled-jsx
styled-components
stylex
(opens in a new tab)tamagui
(opens in a new tab)tss-react
(opens in a new tab)vanilla-extract
(opens in a new tab)
다음 라이브러리는 지원을 진행 중입니다:
알아두면 좋은 점: 우리는 다양한 CSS-in-JS 라이브러리를 테스트 중이며 React 18 기능 및/또는
app
디렉토리를 지원하는 라이브러리에 대한 더 많은 예제를 추가할 예정입니다.
Server Components를 스타일링하려면 CSS Modules 또는 PostCSS나 Tailwind CSS와 같은 CSS 파일을 출력하는 다른 솔루션을 사용하는 것이 좋습니다.
Configuring CSS-in-JS in app
CSS-in-JS를 구성하는 것은 세 단계의 옵트인 과정으로 이루어집니다:
- 렌더링 시 모든 CSS 규칙을 수집하는 스타일 레지스트리.
- 해당 규칙을 사용할 수 있는 콘텐츠 앞에 주입하는 새로운
useServerInsertedHTML
훅. - 초기 서버 사이드 렌더링 중에 앱을 스타일 레지스트리로 감싸는 Client Component.
styled-jsx
Client Components에서 styled-jsx
를 사용하려면 v5.1.0
을 사용해야 합니다. 먼저, 새로운 레지스트리를 생성합니다:
'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
}) {
// 초기 상태로 스타일 시트를 한 번만 생성합니다
// 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 }) {
// 초기 상태로 스타일 시트를 한 번만 생성합니다
// 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>
}
그런 다음, 레지스트리로 루트 레이아웃을 감쌉니다:
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>
)
}
예제는 여기에서 확인하세요 (opens in a new tab).
Styled Components
아래는 styled-components@6
또는 최신 버전을 구성하는 예제입니다:
먼저, next.config.js
에서 styled-components를 활성화합니다.
module.exports = {
compiler: {
styledComponents: true,
},
}
그런 다음, styled-components
API를 사용하여 렌더링 중에 생성된 모든 CSS 스타일 규칙을 수집하는 전역 레지스트리 컴포넌트와 해당 규칙을 반환하는 함수를 생성합니다. 그런 다음 useServerInsertedHTML
훅을 사용하여 루트 레이아웃의 <head>
HTML 태그에 수집된 스타일을 주입합니다.
'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
}) {
// 초기 상태로 스타일 시트를 한 번만 생성합니다
// 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 }) {
// 초기 상태로 스타일 시트를 한 번만 생성합니다
// 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>
)
}
루트 레이아웃의 children
을 스타일 레지스트리 컴포넌트로 감쌉니다:
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>
)
}
예제는 여기에서 확인하세요 (opens in a new tab).
알아두면 좋은 점:
- 서버 렌더링 중에 스타일이 전역 레지스트리에 추출되고 HTML의
<head>
에 플러시됩니다. 이는 스타일 규칙이 해당 규칙을 사용할 수 있는 콘텐츠 앞에 배치되도록 보장합니다. 앞으로 스타일을 주입할 위치를 결정하기 위해 새로운 React 기능을 사용할 수 있습니다.- 스트리밍 중에는 각 청크에서 스타일이 수집되어 기존 스타일에 추가됩니다. 클라이언트 측 하이드레이션이 완료된 후에는
styled-components
가 평소처럼 동작하여 추가 동적 스타일을 주입합니다.- 트리의 최상위에 Client Component를 사용하여 스타일 레지스트리를 사용하는 이유는 이 방법이 CSS 규칙을 추출하는 데 더 효율적이기 때문입니다. 이는 이후 서버 렌더링에서 스타일을 다시 생성하지 않도록 하고, Server Component 페이로드에 스타일이 전송되지 않도록 방지합니다.
- styled-components 컴파일의 개별 속성을 구성해야 하는 고급 사용 사례의 경우, 우리의 Next.js styled-components API 참조를 읽어보세요.