😺

Nextjs - App Router + TypeScript + MUI 最小プロジェクトで作る

2024/10/07に公開

Nextjs - App Router + TypeScript + MUI 最小プロジェクトで作る

概要

現状最新の環境下で構築する上での最小プロジェクト(サンプル)を共有。
公式のドキュメントを活用して導入しているので、ほぼ間違いはないと思う。

以下が現時点(2024.10)での最新バージョン

対象 バージョン
Nextjs v14.2.x
TypeScript v5.x.x
MUI v6.1.x

※ MUIは、旧Material-UIのこと

手順

1. プロジェクトを構築

npx create-next-app@latest --typescript

上記を入力後、下記の通りに選択肢が出るので従って選択する。

Ok to proceed? (y) ・・・ y
? What is your project named? › ・・・ プロジェクト名(小文字)
? Would you like to use ESLint? › No / Yes ・・・ Yes
? Would you like to use Tailwind CSS? › No / Yes ・・・ No
? Would you like to use `src/` directory? › No / Yes ・・・ No
? Would you like to use App Router? (recommended) › No / Yes ・・・ Yes
? Would you like to customize the default import alias (@/*)? › No / Yes ・・・ No

基本全てEnter押下すれば上記の選択肢になる。
今回導入する際にはこのような選択肢だが、ルーティングの箇所以外については任意でもよい。
https://nextjs.org/docs/app/api-reference/cli/create-next-app

2. 必要なモジュールをインストールする

npm i @mui/material @mui/material-nextjs @emotion/cache @emotion/server @emotion/styled

公式のドキュメントよりも多いが、これでも最小限でありインストールしていないと必ずエラーとなる。

3. 各ファイルの編集

layout.tsx、page.tsxの2種のファイルが対象となる。
置き換えするのもバックアップ残すのも任意。

app/layout.tsx

app/layout.tsx
- import type { Metadata } from "next";
- import localFont from "next/font/local";
- import "./globals.css";
+ import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter";
+ import type { ReactNode } from "react";

- const geistSans = localFont({
-   src: "./fonts/GeistVF.woff",
-   variable: "--font-geist-sans",
-   weight: "100 900",
- });
- const geistMono = localFont({
-   src: "./fonts/GeistMonoVF.woff",
-   variable: "--font-geist-mono",
-   weight: "100 900",
- });
-
- export const metadata: Metadata = {
-   title: "Create Next App",
-   description: "Generated by create next app",
- };
+ interface LayoutProps {
+   children: ReactNode;
+ }

- export default function RootLayout({
-   children,
- }: Readonly<{
-   children: React.ReactNode;
- }>) {
+ export default ({ children }: LayoutProps) => {
  return (
-     <html lang="en">
+     <html lang="ja">
-       <body className={`${geistSans.variable} ${geistMono.variable}`}>
+       <body>
+         <AppRouterCacheProvider>
-         {children}
+           {children}
+         </AppRouterCacheProvider>
      </body>
    </html>
  );
}

今回、global.cssとフォントの設定を無効にしているが必要であれば無効にしなくともよい。

app/page.tsx

app/page.tsx
- import Image from "next/image";
- import styles from "./page.module.css";
+ import { Button, TextField, Container, Typography } from "@mui/material";

- export default function Home() {
+ export default () => {
  return (
-     <div className={styles.page}>
-       <main className={styles.main}>
-         <Image
-           className={styles.logo}
-           src="https://nextjs.org/icons/next.svg"
-           alt="Next.js logo"
-           width={180}
-           height={38}
-           priority
-         />
-         <ol>
-           <li>
-             Get started by editing <code>app/page.tsx</code>.
-           </li>
-           <li>Save and see your changes instantly.</li>
-         </ol>
- 
-         <div className={styles.ctas}>
-           <a
-             className={styles.primary}
-             href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
-             target="_blank"
-             rel="noopener noreferrer"
-           >
-             <Image
-               className={styles.logo}
-               src="https://nextjs.org/icons/vercel.svg"
-               alt="Vercel logomark"
-               width={20}
-               height={20}
-             />
-             Deploy now
-           </a>
-           <a
-             href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
-             target="_blank"
-             rel="noopener noreferrer"
-             className={styles.secondary}
-           >
-             Read our docs
-           </a>
-         </div>
-       </main>
-       <footer className={styles.footer}>
-         <a
-           href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
-           target="_blank"
-           rel="noopener noreferrer"
-         >
-           <Image
-             aria-hidden
-             src="https://nextjs.org/icons/file.svg"
-             alt="File icon"
-             width={16}
-             height={16}
-           />
-           Learn
-         </a>
-         <a
-           href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
-           target="_blank"
-           rel="noopener noreferrer"
-         >
-           <Image
-             aria-hidden
-             src="https://nextjs.org/icons/window.svg"
-             alt="Window icon"
-             width={16}
-             height={16}
-           />
-           Examples
-         </a>
-         <a
-           href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
-           target="_blank"
-           rel="noopener noreferrer"
-         >
-           <Image
-             aria-hidden
-             src="https://nextjs.org/icons/globe.svg"
-             alt="Globe icon"
-             width={16}
-             height={16}
-           />
-           Go to nextjs.org →
-         </a>
-       </footer>
-     </div>
+     <Container maxWidth="sm">
+       <Typography variant="h4" component="h1" gutterBottom>
+         Next.js & MUI Sample Page
+       </Typography>
+       <TextField
+         label="Your Name"
+         variant="outlined"
+         fullWidth
+         margin="normal"
+       />
+       <Button variant="contained" color="primary">
+         Click Me
+       </Button>
+     </Container>
  );
}

最小で作成するため、タイトルとテキストフィールド・ボタンの3つのみ表示するUIを設計する。
これらの設定をすることでMUIが利用可能となる。
https://mui.com/material-ui/integrations/nextjs/

Discussion