31
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NextjsのApp RouterにMaterial UIを統合させる

Posted at

はじめに

Material UIはReactのUIコンポーネントライブラリの1つです。名のとおりGoogleのMaterial Designを実装するUIコンポーネントを提供しています(提供されるのは最新のMaterial Design 3ではなくMaterial Design 2です)。
その洗礼された豊富なコンポーネントを手軽に、独自のデザインシステムにカスタマイズしながら利用できる優れたライブラリです。
そんなMaterial UIですが、バージョン5.15.0でNext.jsと統合するためのライブラリとして、@mui/material-nextjsの提供を開始しました。
この記事では@mui/material-nextjsを用いたNext.jsのApp Routerとの統合について解説します。

統合

Nextjsの環境準備

npx create-next-appでNextjsの最新のプロジェクトを作成します。作成のための質問には以下のように答えました。装飾はMaterial UIで行いたいのでTailwind CSSをNoに選択しました。
スクリーンショット 2023-12-17 17.43.50.png

装飾をMaterial UIをベースに行わせるために、CSSやCSS Modulesで書かれている部分を外していきます。CSSファイルは削除して、tsxファイルはそれぞれ以下のように変更します。

layout.tsx
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'

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

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

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  )
}
page.tsx
export default function Home() {
  return <></>
}

Material UIを利用可能に

次に、Material UIに関連するライブラリを導入します。

npm install @mui/material @emotion/react @emotion/styled @mui/material-nextjs @emotion/cache

すでにMaterial UIの環境がある場合は下の2つだけで問題ないです。

npm install @mui/material-nextjs @emotion/cache

パッケージ類の準備は完了なのでlayout.tsxpage.tsxを触っていきます。
まずは、layout.tsxbody以下の要素に対するProviderを設置します。

import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';

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

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

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AppRouterCacheProvider>
          {children}
        </AppRouterCacheProvider>
      </body>
    </html>
  )
}

Nextjsのバージョン14以上を利用の方は上記のように、13以上の場合は'@mui/material-nextjs/v13-appRouter'から同じようにProviderを取得してください。

その後、Material UIを使ったコードをpage.tsxで利用可能になります。

page.tsx
import { Button, Stack, TextField, Typography } from "@mui/material";

export default function Home() {
  return (
    <Stack height="100lvh" justifyContent="center" alignItems="center" gap="32px">
      <Typography id="login_heading" variant="h1" fontSize="1.5rem">ログインフォーム</Typography>
      <Stack component="form" width={560} gap="24px" aria-labelledby="login_heading">
        <TextField label="メールアドレス" />
        <TextField label="パスワード" />
        <Button variant="contained">ログイン</Button>
      </Stack>
    </Stack>
  );
}

出力は以下の通りMaterial UIで装飾されたものです。
スクリーンショット 2023-12-17 18.17.24.png
これで統合は完了です。

AppRouterCacheProvider

@mui/material-nextjsを利用してApp RouterにMaterial UIを統合するためにはAppRouterCacheProviderをルートに設置するだけでした。
AppRouterCacheProviderはReactによって生成されたスタイルを@emotion/cacheを利用して収集して、useServerInsertedHTMLheadに追加しています。
Material UIで使われているEmotionについての解説はありませんが、Nextjsのドキュメントではstyled-jsxstyled-componentなどのCSS in JSについてuseServerInsertedHTMLを用いて同様の処理が書かれています。

オプション

AppRouterCacheProviderにはchildrenの他に2つのpropsをとります。

1つ目はemotion/cachecreaeCacheに渡すための設定に加えてenableCssLayerをキーとした真偽値を任意のオブジェクトとしてoptionsという名前で持ちます。

creaeCacheに渡すための設定はCSP(Content Security Policy)が有効な時に使われるnonce属性や、前処理中にStylisによって実行されるプラグインを渡すstylisPlugins、クラス名のプレフィックスとして利用されるkey、スタイルタグを挿入するDOMを指定するcontainerなどを渡します(参考)。

enableCssLayerは真偽値を値として取り、trueにした場合は生成したスタイルを@layer muiで囲むようになります。これによってEmotionを利用せずに、Tailwind CSSやCSS Modulesなどを用いてMaterial UIのスタイリングを上書きすることが可能となります。@layerは詳細度をより細かく制御するためのアットルールです。

2つ目はCacheProviderです。 デフォルトではemotion/reactCacheProviderが利用されていますが、他のEmotionに対するキャッシュプロバイダを渡せます。

さいごに

NextjsのApp RouterにMaterial UIを統合させる方法を紹介しました。Material UIはこれまでApp Routerで利用するためにはにあるように複雑なコンポーネントを手前で組み込んで利用する必要がありましたが、@mui/material-nextjsの登場で解決しました。

未だ、ほとんどのコンポーネントは'use client'が貼られており、クライアントコンポーネントとして扱うことになってしまいますが、これまでより少し使いやすくなったのではないかなと思います。

31
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?