昨年はサービスのフロントをVueで作ったり、Vue.js+Nuxt.js+Vuetifyを3系にバージョンアップしたり、JestをVitestに切り替えたりと、個人開発のみならず仕事でもフロントはVueをかなり使いました。バックエンドはRailsで開発、7系にバージョンアップもしました。
今年はReactに挑戦して、サービスをリリースしたいと考えています。
(Vueを使った方が早いけどあえて)
フレームワーク選定
React自体はライブラリなので、ルーティング等をしてくれるフレームワークがあると便利。
CSR(Client Side Rendering)かSSR(Server Side Rendering)かで、本番環境で静的ファイルが返せれば良いのか、Nodeサーバーが必要なのかが変わってきます。
また、SEOに力を入れる必要があるならSSR、ログイン前提ならCSRの方がサーバー管理から解放されるので良いです。
本番環境対応の React フレームワーク -> React プロジェクトを始める – React
Next.js, Gatsby and Remix. Which is right for project?• Flexmonster
Next.js: SSR, SSG(Static Site Generation), CSR Remix: SSR Gatsby: SSG
Nuxt.js(Vue)では、nuxt.config.ts「ssr: false」で、CSRのみに設定できましたが、
Next.js(React)のCSRは存在しないと書いている人もいるように、SSR+CSRで使うもののようです。
Gatsbyは、SSGなので、動的サイトには向いていない。
という事で、CSRのみは諦め、シェアの高いNext.jsを使う事にしました。
UIコンポーネントライブラリ選定
NextUI
Next使うならこれかなと思いきや、
NextUI – Beautiful, fast and modern React UI Library
Grid(Vuetifyだとv-row/v-col)がv2に存在しない。v1には存在する。
v2 -> Introduction | NextUI – Beautiful, fast and modern React UI Library
v1 -> Grid | NextUI – Beautiful, fast and modern React UI Library
あと、layout.tsxで呼び出すNextUIProviderに’use client’を付けなきゃいけないのが気になりました。(まだ、ちゃんと理解できていないだけなのか?)
Setup Provider -> Next.js | NextUI – Beautiful, fast and modern React UI Library
Material UI(MUI)
Material Designを使いたいので、こちらを使う事にしました。
Material UI: React components that implement Material Design
当然かもですが、Gridも存在する。
React Grid component – Material UI
Next.jsとMaterial UIインストール
Getting Started: Installation | Next.js
Installation – Material UI
Next.js integration – Material UI
% npx create-next-app@latest next-app-origin ✔ Would you like to use TypeScript? … No / [Yes] ✔ Would you like to use ESLint? … No / [Yes] ✔ Would you like to use Tailwind CSS? … [No] / Yes ← Material UI使うので不要 ✔ Would you like to use `src/` directory? … No / [Yes] ← app使うかsrc/app使うか?好みで ✔ Would you like to use App Router? (recommended) … No / [Yes] ← App Routerが新しい。従来のPages Routerも使える ✔ Would you like to customize the default import alias (@/*)? … No / [Yes] ✔ What import alias would you like configured? … @/* % cd next-app-origin % npm install @mui/material @emotion/react @emotion/styled % npm install @mui/material-nextjs @emotion/cache
src/app/layout.tsx
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
- import './globals.css'
+ import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter'
+ import { ThemeProvider } from '@mui/material/styles'
+ import { theme } from '@/theme'
+ import CssBaseline from '@mui/material/CssBaseline'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
- <html lang="en">
+ <html>
- <body className={inter.className}>{children}</body>
+ <body className={inter.className}>
+ <AppRouterCacheProvider>
+ <ThemeProvider theme={theme}>
+ <CssBaseline />
+ <main>{children}</main>
+ </ThemeProvider>
+ </AppRouterCacheProvider>
+ </body>
</html>
)
}
src/app/globals.css
% rm -f src/app/globals.css
src/theme.ts
'use client'
import { createTheme } from '@mui/material/styles'
const theme = createTheme({
palette: {
mode: 'dark'
}
})
export {
theme
}
トップページ実装
src/app/page.tsx
import NextLink from 'next/link'
import { Grid, Card, CardActionArea, CardContent, Typography, Link, Box } from "@mui/material"
import SignUp from './components/SignUp'
import Infomations from './components/Infomations'
export default function Page() {
return (
<>
<Grid container spacing={2}>
<Grid item xs={12} md={12}>
<Card>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h6" component="div">
Next.js(React/Material UI)のベースアプリケーションです。(サービス概要に差し替え)
</Typography>
<Typography variant="body2" color="text.secondary">
サービスを迅速に立ち上げられるように、よく使う機能を予め開発しています。(サービス説明に差し替え)<br />
リポジトリ: <Link href="https://dev.azure.com/nightonly/_git/next-app-origin" target="_blank" rel="noopener noreferrer">https://dev.azure.com/nightonly/_git/next-app-origin</Link>
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
{true
? <Grid item xs={12} md={6}>
<SignUp />
</Grid>
: ''
}
<Grid item xs={12} md={6}>
<Infomations />
</Grid>
</Grid>
{process.env.NODE_ENV !== 'production'
? <>
<Box sx={{ m: 2 }} />
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<Card>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h6" component="div">
development
</Typography>
<Typography variant="body2">
<Link component={NextLink} href="/development/color">テーマカラー確認</Link>
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
</Grid>
</>
: ''
}
</>
)
}
src/app/page.module.css
% rm -f src/app/page.module.css
src/app/components/SignUp.tsx
'use client'
import NextLink from 'next/link'
import { Card, CardActionArea, CardContent, CardActions, Typography, Divider, Button, Link } from "@mui/material"
import PersonAddIcon from '@mui/icons-material/PersonAdd'
export default function App() {
return (
<Card>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h6" component="div">
アカウント登録
</Typography>
<Typography variant="body2" color="text.secondary">
<Button variant="contained" startIcon={<PersonAddIcon />} href="/users/sign_up">無料で始める</Button>
</Typography>
</CardContent>
<Divider />
<CardActions>
<Typography variant="body2" m={1}>
<Link component={NextLink} href="/users/sign_in">ログイン</Link>
</Typography>
</CardActions>
</CardActionArea>
</Card>
)
}
src/app/components/Infomations.tsx
'use client'
import { Card, CardActionArea, CardContent, Typography, Link } from "@mui/material"
export default function App() {
return (
<Card>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h6" component="div">
大切なお知らせ
</Typography>
<Typography variant="body2">
TODO
</Typography>
</CardContent>
</CardActionArea>
</Card>
)
}
ポート変更
デフォルトの3000だとRailsとかと被るので変えておきます。
個人的にNuxt.js(Vue.js)を5000にしているので、7000に変更。
package.json
"scripts": {
- "dev": "next dev",
+ "dev": "next dev -p 7000",
動作確認
% npm run dev % open http://localhost:7000
今回のコミット内容
Initial commit from Create Next App
Material UIインストール、トップページ実装