yarn add styled-components styled-reset @types/styled-components babel-plugin-styled-components
styled-reset
혹은 styled-normalize
를 설치할 수 있다.styled-components
, @types/styled-components
, babel-plugin-styled-components
를 설치한다.// theme.ts (내부 스타일 요소는 예시입니다.) import "styled-components"; // declare module "styled-components" { export interface DefaultTheme { flex: (direction: string, justify: string, align: string) => string; // colors: { black: string; white: string; }; } }
theme
파일의 인터페이스 타입을 styled-component
의 모듈로 지정해준 후 export
한다.// theme.ts (내부 스타일 요소는 예시입니다.) import { DefaultTheme } from "styled-components"; // const flex = (direction = "row", justify = "center", align = "center") => { return ` display: flex; justify-content: ${justify}; align-items: ${align}; flex-direction: ${direction}; `; }; // const colors = { black: "#0E0E0E", white: "#000000", }; // const theme: DefaultTheme = { flex, colors, }; // export default theme;
styled.d.ts
파일에서 export
한 DefaultTheme
로 theme
의 타입을 지정한다.//GlobalStyle.ts (내부 스타일 요소는 예시입니다.) import { createGlobalStyle } from "styled-components"; import { reset } from "styled-reset"; // const GlobalStyle = createGlobalStyle` ${reset} * { box-sizing: border-box; } `;
// .babelrc { "presets": ["next/babel"], "plugins": [ [ "styled-components", { "ssr": true, "displayName": true, "preprocess": false } ] ] }
Nextjs
는 최초 SSR
이후 부분적으로 CSR
(클라이언트 사이드 렌더링)을 하게 되는데, 이때 server에서 생성되는 class
해시값과 client에서 생성하는 class
해시값이 달라 충돌로 인해 문제가 발생한다. 때문에 babel-plugin-styled-components
및 .babelrc
파일을 설정하도록 하자. (설치 및 파일을 설정했음에도 계속 위와 같은 에러가 발생하다가 npm install
을 통해 전체 모듈을 설치해주니 다시 정상적으로 제기능을 하였다.)import Document, { DocumentContext } from "next/document"; import { ServerStyleSheet } from "styled-components"; // export default 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(); } } }
Next.js는 Pre-rendering
을 통해 Initial load
과정에서 미리 HTML, CSS 등 정적인 요소들을 먼저 렌더링 한 후 JS
파일을 로드하며 Hydration이 이루어진다.
위와 같은 이유로 인해 css-in-js
의 경우, 스타일 요소 또한 늦게 로딩이 된다. (내 경우 아예 로드가 되지 않았다 .. 왜 그런지 이유는 못찾았음..) 이러한 문제점은 next.js 공식문서에서 제공하는 renderPage
를 통해 해결할 수 있다. 즉, index.html
파일에 css-in-js
형식으로 작성된 스타일 요소들을 주입시켜줌으로써 스타일이 뒤늦게 적용되는 문제를 해결할 수 있다.
styled-component 공식문서 에서는 심지어 코드 샘플을 예제로 제공하고 있으며, 적용을 통해 정상적으로 스타일링이 HTML 요소에 적용됨을 확인할 수 있었다.
// _app.tsx import type { AppProps } from "next/app"; // import theme from "../src/styles/theme"; import { ThemeProvider } from "styled-components"; import { GlobalStyle } from "../src/styles/GlobalStyles"; // export default function MyApp({ Component, pageProps }: AppProps) { return ( <ThemeProvider theme={theme}> <GlobalStyle /> <Component {...pageProps} /> </ThemeProvider> ); }