๐Ÿค ์€์ง€log ๐Ÿค

[NextJS] NextJS ์—์„œ Material-ui์™€ Styled-components ์‚ฌ์šฉํ•˜๊ธฐ ๋ณธ๋ฌธ

๐ŸŒท Next JS

[NextJS] NextJS ์—์„œ Material-ui์™€ Styled-components ์‚ฌ์šฉํ•˜๊ธฐ

Eun_zii 2023. 3. 24. 15:03

๐Ÿ“ ํ”„๋กœ์ ํŠธ ์„ธํŒ…

  • ํ•„์š”ํ•œ ๋””ํŽœ๋˜์‹œ๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
npm i -D babel-plugin-styled-component

 

๐Ÿ“ .babelrc

  • ๋จผ์ € ๋ฐ”๋ฒจ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์•„๋ž˜ ํŒŒ์ผ์€ next.js์˜ ssr๊ณผ ์—ฐ๊ด€์ด ์žˆ๋Š”๋ฐ, ssr์— ์˜ํ•ด styled-components ์Šคํƒ€์ผ์ด ์ ์šฉ ์ „์— ํ™”๋ฉด ๋ Œ๋”๋ง์ด ๋˜๋Š” ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.
{
  "presets": ["next/babel"],
  "plugins": [
    [
      "babel-plugin-styled-components",
      { "fileName": true, "displayName": true, "pure": true, "ssr": true }
    ]
  ]
}

 

 

NextJS์—์„œ Styled-components ์‚ฌ์šฉํ•˜๊ธฐ

npm i styled-components npm i @types/styled-components styled-components ๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. npm install babel-plugin-styled-components npm i babe-preset-next babel plugin ์„ ์„ค์น˜ํ•˜๊ณ  .babelrc ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. Next.js๋Š” ํŽ˜์ด์ง€ ์ ‘

eun-jii.tistory.com

 

๐Ÿ“ _document.tsx

  • babel ์„ค์ • ํŒŒ์ผ์„ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์ด์ œ _document ํŒŒ์ผ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. (์•„์ง styled-components๊ฐ€ ์„œ๋ฒ„๋ Œ๋”๋ง์— ์„ธํŒ…๋˜์ง€ ์•Š์Œ)
  • mui๊ฐ€ nextjs์—์„œ ์ž‘๋™ํ•˜๋„๋ก ์„ค์ •ํ•˜์˜€๋Š”๋ฐ ๊ทธ ์œ„์— styled-components๋„ ์‚ฌ์šฉ ํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheet } from "styled-components";
import { ServerStyleSheets } from "@mui/styles";

export default class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

MyDocument.getInitialProps = async ctx => {
  const sheet = new ServerStyleSheet();
  const materialSheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  try {
    ctx.renderPage = () =>
      originalRenderPage({
        enhanceApp: App => props =>
          sheet.collectStyles(materialSheets.collect(<App {...props} />))
      });
      
    const initialProps = await Document.getInitialProps(ctx);
    return {
      ...initialProps,
      styles: (
        <>
          {initialProps.styles}
          {sheet.getStyleElement()}
        </>
      )
    };
  } finally {
    sheet.seal();
  }
};
 

๐Ÿ“ ์„ค๋ช…

  • ServerStyleSheet๋ฅผ ์ด์šฉํ•˜์—ฌ materialSheets๋ผ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • materialSheets๋ฅผ ์ด์šฉํ•˜์—ฌ ์ง€์ •ํ•œ ์ปดํฌ๋„ŒํŠธ(ex: <App />)์˜ ์Šคํƒ€์ผ ์š”์†Œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ๊ทธ ์Šคํƒ€์ผ์„ <style>ํƒœ๊ทธ๋กœ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
  • ์ถ”์ถœํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ Document์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๊ณ  ์†Œ์Šค ํŽ˜์ด์ง€์—์„œ๋„ ์Šคํƒ€์ผ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“ _app.tsx

  • ThemeProvider๋ฅผ ์ฃผ์ž…ํ•˜๊ณ  theme๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ธํŒ…ํ•ฉ๋‹ˆ๋‹ค.
import type { AppProps } from "next/app";
import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider } from 'styled-components'
const theme = {
  primary: 'green',
}

const App = (props: AppProps) => {
  const { Component, pageProps } = props;

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Component {...pageProps} />
    </ThemeProvider>
  );
};

export default App;
 

 

๐Ÿ“ ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ ์‚ฌ์šฉํ•˜๊ธฐ

  • styled-components์—์„œ ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค

styles/global-styles.ts

  • ๋จผ์ € ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
// styles/global-styles.ts

import { createGlobalStyle } from "styled-components";

export const GlobalStyle = createGlobalStyle`
  html,
  body {
    padding: 0;
    margin: 0;
    letter-spacing: -1px;
    font-size: 15px;
    font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
      Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  }

  .txt-c {
    text-align: center;
  }
  .txt-r {
    text-align: right;
  }
  .txt-l {
    text-align: left;
  }
  p {
    margin: 0;
  }
`;
 

 

๐Ÿ“ _app.tsx

  • _app.tsx์— ์‚ฌ์šฉํ•œ ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ์„ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.
import type { AppProps } from "next/app";
import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider } from 'styled-components'
import { GlobalStyle } from "styles/global-styles";

const theme = {
  primary: 'green',
}

const App = (props: AppProps) => {
  const { Component, pageProps } = props;

  return (
    <ThemeProvider theme={theme}>
      <GlobalStyle />
      <CssBaseline />
      <Component {...pageProps} />
    </ThemeProvider>
  );
};

export default App;
 
728x90