[Next.js] styled-components 사용하기
styled-component를 사용할 경우 커스텀이 필요하다.
해당 코드를 추가해주어야 SSR시에 styled가 헤더에 주입된다.추가해주지 않으면 CSS가 적용되지 않고 먼저 렌더링되는 현상이 발생한다.
생략부분에는 메타태그를 넣어주거나 웹폰트를 preload 시켜줄 수 있다.
_document.js
import React from "react";
import Document, { Main, NextScript, Head } from "next/document";
import Helmet from "react-helmet";
import { ServerStyleSheet } from "styled-components";
class MyDocument extends Document {
static async getInitialProps(context) {
const initialProps = await Document.getInitialProps(context)
const sheet = new ServerStyleSheet();
const page = context.renderPage(App => props =>
sheet.collectStyles(
<>
<App {...props} />
</>
)
);
const styleTags = sheet.getStyleElement();
return {...initialProps, ...page, helmet: Helmet.renderStatic(), styleTags};
}
render() {
const { htmlAttributes, bodyAttributes, ...helmet } = this.props.helmet; // helmet으로 부터 받아온다.
const htmlAttrs = htmlAttributes.toComponent();
const bodyAttrs = bodyAttributes.toComponent();
return (
<html {...htmlAttrs}>
<Head>
{this.props.styleTags}
{Object.values(helmet).map(el => el.toComponent())}
</Head>
<body {...bodyAttrs}>
<Main />
<NextScript />
</body>
</html>
);
}
}
export default MyDocument;
.babelrc
최초 SSR 이후 CSR로 라우팅을 하게 되는데,이 때 서버에서 생성하는 해시값과 브라우저에서 생성하는 해시값이 서로 달라서 에러가 발생하게 된다.(Prop className did not match)
이를 해결하기 위해 바벨 플러그인을 설치
{
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-styled-components",
{
"fileName": true,
"displayName": true,
"pure": true
}
]
]
}
fileName : 코드가 포함된 파일명을 알려줌
displayName : 클래스명에 해당 스타일 정보 추가pure : 사용하지 않은 속성 제거