Next.js + styled-componentsでウェブサイトを作り始めてから、ずーっと気になっていました。
ページ表示時に一瞬スタイルが当たってない状態が表示のが。
が。
ついに、その解決方法を見つけました。
この、サーバサイドレンダリングを使えば解決します。
更に、Next.jsでの例は公式がサンプルを用意してくれています。
_document.jsx
import Document from 'next/document'; import { ServerStyleSheet } from 'styled-components'; export default class MyDocument extends Document { static async getInitialProps(ctx) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { ctx.renderPage = () => { return originalRenderPage({ enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />) }); }; const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: ( <> { initialProps.styles } { sheet.getStyleElement() } </> ), } } finally { sheet.seal(); } } }
こちらの、_document.jsxをpage直下に設置すればOKです。
TypeScriptで書くと、
_document.tsx
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 = () => { return originalRenderPage({ enhanceApp: (App) => function MyDocument(props) { return sheet.collectStyles(<App {...props} />); } }); }; const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: ( <> { initialProps.styles } { sheet.getStyleElement() } </> ) }; } finally { sheet.seal(); } } }
という感じです。