Next, typescript styled-components 적용

김정민·2022년 6월 19일
0

Next와 ts에서 styled-components 를 사용할 때 추가적으로 설정해주어야하는 것들이 존재해서 포스팅을 해본다!

기존 Next와 ts를 초기세팅한뒤 보통 styled-components 설정을 해준다.

초기설치

아래에 명령어로 Next에 styled-components를 사용하기 위해 필요한 라이브러리들을 설치합니다

npm install styled-components
npm install @types/styled-components

  • styled-components: styled-components를 사용합니다.
  • @types/styled-components: styled-components를 사용할때 Typescript(타입스크립트)를 사용하기 위한 라이브러리입니다

_document 설정

_document.tsxpages 폴더 내부에 존재하는 모든 페이지에 global한 설정 값을 줄 수 있는 파일입니다.
여기서 style을 불러와서 주입해주는 것이죠. 저는 index.html 의 역할을 한다고 이해하고 있습니다. styled-component 뿐만 아니라 다른 값들도 넣어줄 수 있습니다.

<>
  <link
    rel="stylesheet"
    type="text/css"
    href="static/css/reset.css"
  />
  {initialProps.styles}
  {sheet.getStyleElement()}
</>

이렇게 다른 css 파일도 넣어줄 수 있습니다.

본론으로 돌아와 Next, styled-components에서 _document 설정을 해주는 이유는 Next에서는 초기에 SSR을 사용하게되는데 SSR을 하면서 문제가 생겼습니다. css 파일이 나중에 적용되면서 화면이 깜박거리는 현상이 있었습니다. css가 입혀지기 전에 html 파일이 그대로 노출이되는 거였죠.

간단하게 CSS가 적용되지 않고 먼저 렌더링되는 현상이 발생한다.

_document.tsx

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

class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    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>
          // 생략
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

그래서 해당 코드를 추가해주어야 SSR시에 styled가 헤더에 주입됩니다.

babel

넥스트는 최초 ssr이후 내부 라우팅을 통해 페이지가 이동되면서 csr을 하게되는데 이때, 서버에서 생성하는 해시값과 브라우저에서 생성하는 해시값이 서로 달라서 문제가 발생하게 됩니다.

<Prop className did not match. 에러 발생 >

해결을 위해 설치

npm install babel-plugin-styled-components

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "babel-plugin-styled-components",
      { "fileName": true, "displayName": true, "pure": true, "ssr": true }
    ]
  ]
}
  • fileName : 코드가 포함된 파일명을 알려줌
  • displayName : 클래스명에 해당 스타일 정보 추가
  • pure : 사용하지 않은 속성 제거
  • ssr : server side rendering

해당 코드를 추가

globalstyle

마지막으로 globalstyle을 추가해준다.

import { createGlobalStyle } from "styled-components";
import { reset } from "styled-reset";
import { media } from "./theme";

export const GlobalStyle = createGlobalStyle`
    ${reset}
    :focus {
        outline: none;
        border: none;
    }
    ::-webkit-scrollbar {
        display: none;
    }
    html{
        font-size: 11px;
        -webkit-text-size-adjust: none;
        font-family: -apple-system,BlinkMacSystemFont,helvetica,Apple SD Gothic Neo,sans-serif;       
        font-display: fallback;
        ${media.tablet}{
            font-size: 10px;
        }
        -ms-overflow-style: none;
        scrollbar-width: none;
    }
    button {
        background: none;
        padding: 0;
        border: none;
        cursor: pointer;
        &:disabled {
            cursor: default;
            fill: #f2f3f4;
        }
    }

    .pc-tablet-only {
        display: block;
        ${media.mobile} {
            display: none;
        }
    }
    .tablet-mobile-only{
        display: none;
        ${media.tablet}{
            display:block;
        }
    }
    .mobile-only {
        display: none;
        ${media.mobile} {
            display: block;
        }
    }
`;

0개의 댓글