Next.js入門 - Reactで本格的なWebアプリを作るならこれ一択
はじめに
結論から言うと、Reactでちゃんとしたプロダクションレベルのアプリを作りたいなら、Next.js一択ですね。
Next.jsはVercel社が開発しているReactフレームワークで、GitHubスター数は136,000以上。これ、意外とすごい数字で、フロントエンド界隈ではトップクラスの人気を誇っています。最新バージョンはv16.0.7(2025年12月リリース)で、NotionやNike、Washington Postといった世界的な企業でも採用されています。
個人的には、素のReactで開発していた頃と比べて、開発効率が段違いに上がったと感じています。ルーティング、SSR/SSG、API、画像最適化...これらを全部自前で用意する必要がないのは本当にありがたい。
特徴・メリット
1. App Routerでルーティングが超シンプル
ファイルシステムベースのルーティングなので、app/about/page.tsxを作れば/aboutにアクセスできる。これだけ。
正直なところ、React Routerの設定で消耗していた時間がゼロになりました。ネストしたレイアウトも直感的に書けるので、複雑な画面構成でも迷わない。
2. Server Componentsで爆速表示
React Server Components(RSC)に対応していて、サーバーサイドでコンポーネントをレンダリングできます。クライアントに送るJavaScriptの量が減るので、初期表示が速い。
30代になって思うのは、ユーザー体験って結局「速さ」に集約されるという話。Core Web Vitalsのスコアも上げやすくなります。
3. Server Actionsでバックエンドも書ける
これがNext.js 13以降の目玉機能。フォーム処理やデータ更新を、APIエンドポイントを別途作らずに関数一発で書ける。
'use server'
export async function createPost(formData: FormData) {
const title = formData.get('title')
// データベースに保存
await db.post.create({ data: { title } })
}
フロントとバックの境界がほぼなくなるので、開発のQOL上がりますね。
4. Turbopackで爆速ビルド
Rust製のバンドラー「Turbopack」を搭載。正直、Webpackの頃のビルド待ち時間を考えると、時短効果がえぐい。HMR(ホットリロード)も体感で数倍速い。
5. 画像・フォント最適化が標準装備
next/imageコンポーネントを使うだけで、WebP変換、遅延読み込み、レスポンシブ対応が全自動。フォントもnext/fontで最適化されるので、CLSの問題とはおさらばです。
インストール方法
推奨:create-next-appを使う
# npmの場合
npx create-next-app@latest my-app
# yarnの場合
yarn create next-app my-app
# pnpmの場合
pnpm create next-app my-app
対話形式で設定を選べます:
✔ Would you like to use TypeScript? Yes
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? Yes
✔ Would you like your code inside a `src/` directory? No
✔ Would you like to use App Router? (recommended) Yes
✔ Would you like to use Turbopack for `next dev`? Yes
コスパ的に、TypeScriptとApp Routerは必ず有効にしておくべき。後から変更するのは面倒なので。
プロジェクト起動
cd my-app
npm run dev
http://localhost:3000でアプリが立ち上がります。
基本的な使い方
ページの作成(App Router)
// app/page.tsx(トップページ)
export default function Home() {
return (
<main>
<h1>Welcome to Next.js</h1>
<p>フルスタックReactフレームワーク</p>
</main>
)
}
// app/about/page.tsx(/aboutページ)
export default function About() {
return (
<main>
<h1>About</h1>
<p>このサイトについて</p>
</main>
)
}
レイアウトの共通化
// app/layout.tsx
import './globals.css'
export const metadata = {
title: 'My App',
description: 'Next.jsで作ったアプリ',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ja">
<body>
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
{children}
<footer>© 2025 My App</footer>
</body>
</html>
)
}
データフェッチ(Server Components)
// app/posts/page.tsx
interface Post {
id: number
title: string
body: string
}
async function getPosts(): Promise<Post[]> {
const res = await fetch('https://jsonplaceholder.typicode.com/posts', {
next: { revalidate: 3600 } // 1時間キャッシュ
})
return res.json()
}
export default async function PostsPage() {
const posts = await getPosts()
return (
<main>
<h1>記事一覧</h1>
<ul>
{posts.slice(0, 10).map((post) => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.body.slice(0, 100)}...</p>
</li>
))}
</ul>
</main>
)
}
これ、asyncコンポーネントでそのままfetchできるのが革命的なんですよ。useEffectとuseStateのボイラープレートから解放される。
クライアントコンポーネント
インタラクティブな処理が必要な場合は'use client'を付ける:
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
)
}
APIルート(Route Handlers)
// app/api/hello/route.ts
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json({ message: 'Hello from API!' })
}
export async function POST(request: Request) {
const body = await request.json()
// 処理...
return NextResponse.json({ received: body })
}
実践的なユースケース
1. 静的サイト生成(SSG)でブログを作る
// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation'
// ビルド時に生成するパスを指定
export async function generateStaticParams() {
const posts = await getAllPosts()
return posts.map((post) => ({
slug: post.slug,
}))
}
export default async function BlogPost({
params,
}: {
params: { slug: string }
}) {
const post = await getPostBySlug(params.slug)
if (!post) {
notFound()
}
return (
<article>
<h1>{post.title}</h1>
<time>{post.date}</time>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
)
}
2. Server Actionsでフォーム処理
// app/contact/page.tsx
import { redirect } from 'next/navigation'
async function submitForm(formData: FormData) {
'use server'
const name = formData.get('name') as string
const email = formData.get('email') as string
const message = formData.get('message') as string
// バリデーション
if (!name || !email || !message) {
throw new Error('全項目を入力してください')
}
// データベースに保存 or メール送信
await saveContact({ name, email, message })
redirect('/contact/thanks')
}
export default function ContactPage() {
return (
<form action={submitForm}>
<input type="text" name="name" placeholder="お名前" required />
<input type="email" name="email" placeholder="メールアドレス" required />
<textarea name="message" placeholder="メッセージ" required />
<button type="submit">送信</button>
</form>
)
}
3. Middlewareで認証チェック
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const token = request.cookies.get('token')
// 認証が必要なパスをチェック
if (request.nextUrl.pathname.startsWith('/dashboard')) {
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
}
return NextResponse.next()
}
export const config = {
matcher: '/dashboard/:path*',
}
4. 動的OGP画像生成
// app/api/og/route.tsx
import { ImageResponse } from 'next/og'
export const runtime = 'edge'
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const title = searchParams.get('title') ?? 'Default Title'
return new ImageResponse(
(
<div
style={{
fontSize: 60,
background: 'linear-gradient(to bottom, #1a1a2e, #16213e)',
color: 'white',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{title}
</div>
),
{
width: 1200,
height: 630,
}
)
}
まとめ
Next.jsは、Reactでプロダクションレベルのアプリを作るなら間違いなく最適解です。
- ルーティング不要: ファイルベースで自動的に設定される
- パフォーマンス最適化: Server Components、画像最適化、Turbopackが標準
- フルスタック対応: Server Actions、Route Handlersでバックエンドも書ける
- デプロイが簡単: Vercelなら数クリック、他のプラットフォームでも対応
- TypeScriptファースト: 型安全な開発が当たり前にできる
正直なところ、2025年の今、新規プロジェクトでReactを使うならNext.jsを選ばない理由がない。学習コストはあるけど、それ以上のリターンがあります。
まずはcreate-next-appで触ってみてください。きっとその快適さに驚くはず。