728x90
ISSUE
Next.js에서 styled-components로 작성한 Theme Provider를 전달하였더니 다음과 같은 에러가 나타나며 실행이 되지 않았습니다.
next-dev.js
Warning: Prop `className` did not match. Server: '어쩌구저쩌구' Client: '어쩌구저쩌구'
REASON
NextJS는 초기 렌더링만 서버가 담당(SSR)하고 그 이후에는 서버를 거치지 않은 채 내부 라우팅을 이용해 페이지가 이동되면서 브라우저에서 렌더링(CSR)을 하게 됩니다.
첫 화면 로딩시에는 SSR로 렌더링하면서 오류가 발생하지 않지만 그 이후 부터는 CSR로 렌더링하면서, 서버에서의 클래스명과 클라이언트에서 클래스명이 달라져서 생기는 오류입니다.
SOLUTION
해결 방법은 두 가지가 있는데, 아래 두가지 방법 중 하나로 해결하면 됩니다. 만일 사용중인 Next.js가 최신 버전이라면 두번째 방법을 사용하는 것을 추천합니다.
💡 NOTE: 두 가지 방법을 동시에 적용하면 바벨이 충돌나서 제대로 작동하지 않습니다.
1️⃣ 첫번째 방법
- babel-plugin-styled-components를 설치한다.
npm install --save-dev babel-plugin-styled-components
yarn add --dev babel-plugin-styled-components // --dev : Add a package as a dev dependency
- 프로젝트 루트에 .babelrc를 생성한 뒤 설정을 추가하고, 서버를 재실행합니다.
// .babelrc
{
"presets": ["next/babel"], // -> 이거 설정안하면 빌드안됨
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": false
}
]
]
}
- _document.tsx에 다음의 내용을 넣어줍니다.
// pages/_document.tsx
import Document, { 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()
}
}
}
Reference
- styled-component: babel plugin
- yarn : yarn add options '--dev'
- github issue#1239: github/styled-components
2️⃣ 두번째 방법
Next.js 최신 버전에서는 styled-components의 ssr를 잘 지원해주므로, Next.js의 컴파일러 옵션만으로 간단하게 해결할 수 있습니다.
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
compiler: {
// ssr and displayName are configured by default
styledComponents: true,
},
};
export default nextConfig;
Reference
- Styled Components: Next.js Compiler