카테고리 없음

Next.JS 프로젝트 렌더링시 Styled-components가 깨지는 현상을 해결해보자

썽연 2022. 11. 13. 15:09
728x90

CSS-In-JS 방식인 Styled-components로 스타일을 다 하였지만,

리렌더링이 될 시 스타일이 적용이 안되는 문제가 발생하였다.

NextJS의 렌더링 및 스타일이 깨지는 이유를 알아보자

Next.js는 기본적으로 페이지를 ServerSide Rendering을 한다.

즉, pre-render을 한다는 것이다.

Server Side에서 html파일을 구성하여 브라웆 측에 전달하여 렌더링한다.

이후, JavaScript 파일이 로드되어 자바스크립트 코드가 적용된다.

즉, HTML → JavaScript로 인해 스타일이 적용되지 않은 html코드가 먼저 렌더링이 된다!

해결법

renderPage 함수를 커스터마이징하자!

Next.js 공식 홈페이지에서 CSS-In-JS 방식을 사용할 때만 수정하라고 나와있다.

pages/_document.ts파일을 만들고 아래와 같이 수정해주면된다.

import Document, {
  Html,
  Head,
  Main,
  NextScript,
  DocumentContext,
  DocumentInitialProps,
} from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: [
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>,
        ],
      };
    } finally {
      sheet.seal();
    }
  }
  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

위 코드와 같이 적용을 하면, pre-render할 때, 스타일도 보이는 것을 확인할 수 있다.

이후, className에 대한 콘솔에러가 뜨는 것을 확인할 수 있다.

바벨 파일을 설치

yarn add babel-plugin-styled-components

.babelrc 파일 생성

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "styled-components",
      {
        "ssr": true,
        "displayName": true,
        "preprocess": true
      }
    ]
  ]
}

위 코드를 작성 후, 서버를 껏다키면 에러가 없어지는 것을 확인할 수 있다.

728x90