Next.js + Typescript 에 Styled-component 적용

Seunghwa's Devlog·2021년 3월 4일
2
  • 라이브러리 설치
yarn add styled-components

Javascript를 사용할 때는 위의 명령어로 설치를 하면 되지만, Typescript를 적용하면 styled-component를 인식하지 못한다. Typescript에서는 리액트 라이브러리에 대한 type이 정의가 되어있지 않기 때문이다. 따라서 type을 정의해 놓은 라이브러리도 설치해야 한다.

yarn add @types/styled-components
  • index.tsx에 적용
import Head from 'next/head';
import styled from "styled-components";

export default function Home(){
  return(
   <HomeBlock>
     <Head>
       <title>Create Next App</title>
     </Head>
     <div>
       <h1>Next.js + Typescript</h1>
     </div>
   </HomeBlock>
  );
}

const HomeBlock = styled.div `
  min-height : 100vh;
  padding : 0 0.5rem;
  display : flex;
  flex-direction : column;
  justify-content : center;
  align-items : center;
`;
  • style 구조
    이 설정은 개발자마다 다를 수 있음
├── styles
│   ├── global-styles.ts           # reset 또는 공통적으로 사용하는 css
│   ├── theme.ts                   # 공통적으로 사용할 테마(media query, color 등)
│   └── styled-components.ts       # 테마를 포함하여 재정의한 styled-components
  • .babelrc
    styled-component를 사용하다 보면 문자열 안에 스타일이 들어가므로 처리를 위해 별도로 babel이필요하다
yarn add -dev babel-plugin-styled-components

라이브러리 설치 후 root 디렉토리에 .babelrc 파일을 만들고 설정을 다음과 같이 한다.

{
    "presets" : ["next/babel"],
    "plugins": [
        [
            "styled-components",
            {
                "ssr": true,
                "displayName": true,
                "preprocess": false
            }
        ]
    ]
}
  • styled-components pages/_app.tsx 에 전역적으로 설정
    ex)
import {AppProps} from 'next/app'
import {ThemeProvider} from "../styles/styled-components";
import {GlobalStyle} from "../styles/global-styles";
import {theme} from "../styles/theme";

function App({Component, pageProps} : AppProps){
    return (
        <ThemeProvider theme={theme}>
            <GlobalStyle />
            <Component {...pageProps} />
        </ThemeProvider>
    );
}


export default App

★ Next.js에서 styled-component를 사용하면 CSS 로딩이 늦게 되어 깜빡이는 현상 발생 → HTML은 SSR로 미리 렌더링 시키지만 styled-component의 스타일들은 사용자가 접속 시 변환되기 때문

따라서 _document.tsx 파일에 css를 미리 적용시켜야 한다.

  • SSR 에서도 styled-component를 사용하도록 설정
    _document.tsx는 pages 폴더 내부에 존재하는 모든 페이지에 global한 설정 값을 줄 수 있는 파일이다.
export default class MyDocument extends Document{
    static async getInitialProps(ctx : DocumentContext){
        // 스타일 구성 요소의 ServerStyleSheet 클래스를 인스턴스화 한다
        const sheet = new ServerStyleSheet();
        const originalRenderPage = ctx.renderPage;

        try{
            // renderPage : 이 메서드에 연결하여 초기 페이지 로드 시 서버 측 자식 구성 요소의 스타일 분석
            // renderPage를 커스텀 하는 이유는 서버 측 렌더링에서 제대로 작동하기 위해 애플리케이션을 래핑해야 하는 css-in-js 라이브러리와 함께 사용하기 위한 것
            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();
        }
    }
}
profile
에러와 부딪히고 새로운 것을 배우며 성장해가는 과정을 기록합니다!

2개의 댓글

comment-user-thumbnail
2021년 11월 19일

Next.js에서 styled-component를 사용하면 CSS 로딩이 늦게 되어 깜빡이는 현상 발생하면 sass를 사용했을때도 동일한 현상이 발생하나요?

1개의 답글