React 와 다른 부분만 기록 해 둔다.
내 소개 사이트에 적용...
Next.js Docs
Next.js github
Custom app
Custom document
app.tsx 와 document 파일을 custimizing 해 줘야 한다. (create next 로 만들어서 기존에 파일이 없었다. 파일을 추가 해 주고 커스터 마이징 해줬다.)
app 에서 style 을 뿌려주고, document 는 Next.js 와 styled-component 가 그려내는 방식이 달라서 custom 한다.
Next.js 는 서버에서 렌더링을 모두 마치지만(SSR) styled-component는 Client 단에서 그려내기 때문에 CSS가 입혀지기 전에 그려내 버린다. 따라서 document 에서 미리 CSS 를 적용 시킨다.
// pages/_app.tsx
import type { AppProps } from "next/app";
import { GlobalStyle } from "../styles/GlobalStyle";
import { ThemeProvider } from "styled-components";
import theme from "../styles/theme";
import CustomHead from "../components/CustomHead";
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<ThemeProvider theme={theme}>
<GlobalStyle />
<CustomHead />
<Component {...pageProps} />
</ThemeProvider>
</>
);
}
export default MyApp;
// pages/_document.tsx
import Document, {
DocumentContext,
DocumentInitialProps,
Html,
Head,
Main,
NextScript,
} from "next/document";
import { ServerStyleSheet } from "styled-components";
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();
}
}
// Head 안의 link 처럼 meta tag 나 웹폰트를 추가 할 수 있다.
render() {
return (
<Html>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Roboto&display=swap"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
npm install --save-dev babel-plugin-styled-components
styled-component babel plugin
최초 SSR 이후부터는 CSR로 라우팅을 한다. 해당 플러그인을 설치하지 않았다면, 서버에 발생했던 해시값과 브라우저에서 발생한 해시값이 서로 달라져서 에러를 뱉어낸다. 내가 그랬다...{ "presets": ["next/babel"], "plugins": ["babel-plugin-styled-components"] }