Next.js に MUI 5 を統合する手順
1. Next.js アプリの作成と依存関係のインストール
まず、新しい Next.js アプリを作成し、必要な依存関係をインストールします。
npx create-next-app my-app
cd my-app
npm install @mui/material @emotion/react @emotion/styled @mui/icons-material @emotion/server
2. MUI テーマの定義
MUI テーマを定義して、アプリケーション全体にテーマを適用します。
テーマの設定は、src/theme.ts
という名前のファイルに定義します。このファイルには、カスタムのカラーパレットやテキストのスタイルなどを指定できます。
// src/theme.ts
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#2196f3',
},
secondary: {
main: '#f50057',
},
},
});
export default theme;
3. Emotion キャッシュの設定
Emotion キャッシュを設定し、アプリケーション内でスタイルが一貫して適用されるようにします。Emotion キャッシュは、CSS スタイルを効率的に処理するためのツールです。
utils/createEmotionCache.ts
ファイルを作成して、Emotion キャッシュをセットアップします。
// utils/createEmotionCache.ts
import createCache from "@emotion/cache";
const isBrowser = typeof document !== "undefined";
export default function createEmotionCache() {
let insertionPoint;
if (isBrowser) {
const emotionInsertionPoint = document.querySelector<HTMLMetaElement>(
'meta[name="emotion-insertion-point"]'
);
insertionPoint = emotionInsertionPoint ?? undefined;
}
return createCache({ key: "mui-style", insertionPoint });
}
4. _app.tsx ファイルの更新
_app.tsx
ファイルは、すべてのページで共通の設定を行う場所です。ここで Emotion キャッシュを提供し、テーマを適用します。
このファイルでは、ThemeProvider
を使用してテーマをコンポーネントツリーに適用します。また、CssBaseline
コンポーネントを使って、基本的なブラウザのスタイルをリセットし、MUI のスタイルを適切に適用します。
// pages/_app.tsx
import React from 'react';
import { AppProps } from 'next/app';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { CacheProvider, EmotionCache } from "@emotion/react";
import createEmotionCache from "…/utils/createEmotionCache";
import theme from '…/src/theme';
const clientSideEmotionCache = createEmotionCache();
export interface MyAppProps extends AppProps {
emotionCache?: EmotionCache;
}
function MyApp({ Component, pageProps }: MyAppProps) {
const { emotionCache = clientSideEmotionCache, …restPageProps } = pageProps;
return (
<CacheProvider value={emotionCache}>
<ThemeProvider theme={theme}>
<CssBaseline />
<Component {…restPageProps} />
</ThemeProvider>
</CacheProvider>
);
}
export default MyApp;
5. _document.tsx ファイルの追加
_document.tsx
ファイルは、アプリケーション全体に共通の HTML 構造をカスタマイズするためのファイルです。ここで Emotion スタイルを効果的に適用するための設定を行います。
このファイルでは、getInitialProps
関数を使用して Emotion スタイルを効果的に読み込み、SSR での正しいスタイルの適用を確保します。また、emotionStyleTags
を使用してスタイルをレンダリングします。
// pages/_document.tsx
import Document, {
Html,
Head,
Main,
NextScript,
DocumentProps,
DocumentContext,
} from "next/document";
import { AppType } from "next/app";
import { MyAppProps } from "./_app";
import createEmotionServer from "@emotion/server/create-instance";
interface MyDocumentProps extends DocumentProps {
emotionStyleTags: JSX.Element[];
}
export default class MyDocument extends Document<MyDocumentProps> {
static async getInitialProps(ctx: DocumentContext) {
const originalRenderPage = ctx.renderPage;
// Create an Emotion cache instance.
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (
App: React.ComponentType<React.ComponentProps<AppType> & MyAppProps>
) => (props) => <App {…props} emotionCache={cache} />,
});
const initialProps = await Document.getInitialProps(ctx);
// Extract the critical CSS and return it as a prop.
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={${<span class="hljs-attr">style.key</span>} ${<span class="hljs-attr">style.ids.join</span>(" ")}
}
key={style.key}
dangerouslySetInnerHTML={{ __html: style.css }}
/>
));
return {
…initialProps,
emotionStyleTags,
};
}
render() {
const { emotionStyleTags } = this.props;
return (
<Html lang="en">
<Head>
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="emotion-insertion-point" content="" />
{emotionStyleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
これで、上記の手順に従って Next.js アプリに MUI 5 を統合し、テーマを適用することができます。
出来上がったソースコードはこちら:https://github.com/kaoru20141104/next-mui-app-demo