NextJS 13.4 Appdir + Mui + Tailwind 초기세팅

taeyooooon·2023년 5월 6일
2
post-thumbnail

최근에 Next 13.4 버전이 릴리즈 되면서 App 디렉토리 방식이 Stable 상태로 변경되었습니다.
-> https://nextjs.org/blog/next-13-4

새로운 프로젝트를 App 디렉토리 방식으로 초기세팅을 하던 중 겪은 문제에 대해서 정리하는 글입니다.

1. CNA -> mui 설치

yarn add @mui/material @emotion/react @emotion/styled

아래 공식문서에 적혀있는 절차대로 진행하면 됩니다.
https://mui.com/material-ui/guides/interoperability/#tailwind-css

다만 공식문서에 있는 내용 그대로 진행했더니 아래 4번 포탈관련 설정이 적용이 안되어서
important 값을 "__next"가 아닌 "body"로 설정했습니다.

2. tailwind.config 수정

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  important: 'body',
  theme: {
    extend: {},
  },
  plugins: [],
  corePlugins: {	// 추가
    preflight: false,
  },
}

3. CSS 주입순서 변경

layout.tsx에 바로 Provider를 생성할 경우 아래의 에러가 나올텐데

TypeError: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component

저는 provider들을 따로 관리하기 위한 클라이언트 컴포넌트를 따로 만들었습니다.

// layout.tsx
import React from 'react'
import '../styles/globals.css'
import { Inter } from 'next/font/google'
import Providers from './providers'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ko">
      <body className={inter.className}>
        <div id="__next">
          <Providers>
            <main>{children}</main>
          </Providers>
        </div>
      </body>
    </html>
  )
}

NextJS 13 App 디렉토리 방식부터 root div에 #__next가 사라졌습니다....
https://github.com/vercel/next.js/discussions/45541
이거 때문에 오래 해맸는데
직접 layout.tsx에서 #__next 로 감싸주면 해결됩니다

// providers.tsx
'use client'

import React from 'react'
import { CssBaseline, StyledEngineProvider } from '@mui/material'

const Providers = ({ children }: { children: React.ReactNode }) => {
  return (
    <>
      <StyledEngineProvider injectFirst>
          <CssBaseline />
          {children}
      </StyledEngineProvider>
    </>
  )
}
export default Providers

4. 포탈 관련 설정

아래는 포탈관련해서 스타일이 안입혀지는 이슈에 해당하는 설정입니다.

// providers.tsx
'use client'

import React from 'react'
import { CssBaseline, StyledEngineProvider, ThemeProvider, createTheme } from '@mui/material'

const Providers = ({ children }: { children: React.ReactNode }) => {
  let rootElement
  if (typeof window !== 'undefined') {
    rootElement = window.document.body
  }

  const theme = createTheme(
    rootElement !== undefined
      ? {
          components: {
            MuiPopover: {
              defaultProps: {
                container: rootElement,
              },
            },
            MuiPopper: {
              defaultProps: {
                container: rootElement,
              },
            },
            MuiModal: {
              defaultProps: {
                container: rootElement,
              },
            },
          },
        }
      : {},
  )

  return (
    <>
      <StyledEngineProvider injectFirst>
        <ThemeProvider theme={theme}>
          <CssBaseline />
          {children}
        </ThemeProvider>
      </StyledEngineProvider>
    </>
  )
}
export default Providers

처음에는 단순히 클라이언트 컴포넌트라서 const rootElement = window.document.body 로 바로 접근하면 되는 줄 알았는데 document is not defined 라는 에러가 나와서
검색해보니 클라이언트 컴포넌트도 서버측에서 prerender 하기 때문에 document 객체가 아직 존재하지 않아서 에러가 발생합니다.
해결방법 -> https://heokknkn.tistory.com/35

소스코드 : https://github.com/Taeyooooon/next-boilerplate-appdir

++ 5/17 추가

tailwind.config 에서 preflight false 옵션을 줘서 tailwind 에서 기존방식대로 border 스타일을 주면 말을 안듣는데 그럴때 global.css 에 아래 코드 추가해주면 됩니다.
상단에서 설정했던 mui의 CssBaseLine 가 reset css가 아닌 normalize css를 추구하기 때문이다.

*,
::before,
::after {
  border-width: 0;
  border-style: solid;
  border-color: theme('borderColor.DEFAULT', currentColor);
}

https://tailwindcss.com/docs/preflight#border-styles-are-reset-globally

참고한 링크

https://mui.com/material-ui/guides/interoperability/#tailwind-css

profile
응애🐣 프론트엔드

0개의 댓글