Next와 styled-components를 쓰게 되면 브라우저 로딩이 끝나야 CSS 적용이 되거나 새로고침을하게되면 css가 적용이 안된다.
Next가 먼저 정적으로 생성된 HTML을 렌더후 나머지 JS파일을 로드하게 된다.
JS에 의해 동적으로 CSS가 생성되는 CSS-In-Js 방식인 styled-components는 위와 같은 과정에서 생성되는 HTML에 우리의 코드가 함께 빌드 되지않는다.
자세한 설명은 이 블로그를 참고하길 바란다.
renderPage 함수를 커스터마이징을 통해 해결해야한다.
renderPage 함수 커스터마이징은 반드시 CSS-In-Js 방식 사용 할때만 수정하라고 한다.
앞으로는 next를 사용할 때에는 Sass css-in-css방식을 적용해보아야겠다.
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
import { ServerStyleSheet } from 'styled-components'
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()
}
}
}
여기서 className did not match는 다른 방법으로 해결해야했다.
서버에서 받은 해시+클래스명과 새로고침후 클라이언트에서 받은 해시+클래스명이 달라서 발생하는 문제다.
npm i babel-plugin-styled-components
.babelrc를 생성후 아래 코드 작성
{
"presets": ["next/babel"],
"plugins": ["babel-plugin-styled-components"]
}