[m] next에 styled-components 적용 (app router)

김남경·2023년 8월 19일
2

project

목록 보기
36/36

스타일 적용 시점

next는 SSR로 pre-rendering을 한다 즉 서버사이드에서 HTML+CSS를 브라우저에 전달 후 렌더링하고 다음 JS파일이 로드된다 그래서 CSS-IN-JS의 경우 스타일이 적용되지 않은 HTML파일이 렌더링되게 되는 문제가 있다

해결하기

설치

npm install styled-components

next.config.mjs 설정

const nextConfig = {
  compiler: {
    styledComponents: true,
  ...
  },
};

registry 추가

'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
}) {
  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>
  )
}

layout 적용

 	<body>
        <StyledComponentsRegistry>
          {props.children}
        </StyledComponentsRegistry>
      </body>

적용해보면 아래와 같은 에러가 출력된다

Syntax error: "next/font" requires SWC although Babel is being used
due to a custom babel config being present.

babel보다는 SWC를 추천한다는 것 그래서 SWC 설정을 추가한다

SWC plugin 설정

설치

npm i -D @swc/plugin-styled-components

.swcrc 추가

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "ssr": true
          }
        ]
      ]
    }
  }
}

StyleProvider 만들기

다른 Provider도 추가할 예정이므로 분류가 같은 것끼리 별도 파일로 관리하기로 한다

Global Style 추가

'use client'

import { createGlobalStyle } from 'styled-components'

const GlobalStyles = createGlobalStyle`
  body{
    background: beige;
  }
`

export default GlobalStyles

theme 추가

const theme = {
  colors: {
    colorName1: '#aabbcc',
    colorName2: 'hsla(50, 60%, 70%, 0.5)',
  },
}

export default theme

theme Type 추가

//types/styled.d.ts

import 'styled-components'
import { theme } from '@/styles/theme'

type Theme = typeof theme

declare module 'styled-components' {
  export interface DefaultTheme extends Theme {}
}

ThemeProvider 추가

'use client'

import { ThemeProvider } from 'styled-components'
import StyledComponentsRegistry from '@/styles/Registry'
import GlobalStyles from '@/styles/globalStyles'
import theme from '@/styles/theme'

export default function StylesProvider({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <StyledComponentsRegistry>
      <GlobalStyles />
      <ThemeProvider theme={theme}>{children}</ThemeProvider>
    </StyledComponentsRegistry>
  )
}

참고

[NextJS] styled-components와 함께 사용하기

css-in-js : styled-components

Using Styled-Components with Next.js v13 (TypeScript)

profile
기본에 충실하며 앞으로 발전하는

0개의 댓글