next(Next.js)の使い方 — The React Framework 完全ガイド
この記事は Next.js v16.2.2 時点の情報に基づいています。バージョンによってAPIや挙動が異なる場合があります。
一言でいうと
Next.js は、React ベースのフルスタック Web フレームワークです。 サーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、API ルート、ファイルベースルーティングなどを標準搭載し、React アプリケーションのプロダクション運用に必要な機能をオールインワンで提供します。
どんな時に使う?
- SEO が重要な Web サイト・メディアサイトを構築するとき — SSR/SSG により、クローラーに完全なHTMLを返せます。
- React でフルスタックアプリケーションを開発するとき — フロントエンドとバックエンド(API Routes / Server Actions)を一つのプロジェクトで管理できます。
- パフォーマンスを最適化した SPA / MPA を素早く立ち上げたいとき — コード分割、画像最適化、フォント最適化などが組み込みで提供されます。
インストール
新規プロジェクトの作成(推奨)
npx create-next-app@latest my-app
既存プロジェクトへの追加
# npm
npm install next react react-dom
# yarn
yarn add next react react-dom
# pnpm
pnpm add next react react-dom
package.json にスクリプトを追加
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
}
基本的な使い方 — Next.js のファイルベースルーティング
Next.js は App Router(app/ ディレクトリ)を標準のルーティング方式として採用しています。
ディレクトリ構成例
my-app/
├── app/
│ ├── layout.tsx # ルートレイアウト
│ ├── page.tsx # / にマッピング
│ ├── about/
│ │ └── page.tsx # /about にマッピング
│ └── blog/
│ ├── page.tsx # /blog にマッピング
│ └── [slug]/
│ └── page.tsx # /blog/:slug にマッピング
├── public/
├── next.config.ts
├── package.json
└── tsconfig.json
ルートレイアウト(app/layout.tsx)
// app/layout.tsx
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "My Next.js App",
description: "Next.js で構築したアプリケーション",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>{children}</body>
</html>
);
}
ページコンポーネント(app/page.tsx)
// app/page.tsx
export default function HomePage() {
return (
<main>
<h1>ようこそ Next.js へ</h1>
<p>これはトップページです。</p>
</main>
);
}
動的ルート(app/blog/[slug]/page.tsx)
// app/blog/[slug]/page.tsx
type Props = {
params: Promise<{ slug: string }>;
};
export default async function BlogPost({ params }: Props) {
const { slug } = await params;
return (
<article>
<h1>記事: {slug}</h1>
</article>
);
}
注意: Next.js 15 以降、
paramsは Promise として渡されるようになりました。awaitが必要です。
よく使う API — Next.js の主要機能5選
1. Server Components でのデータフェッチ
App Router のコンポーネントはデフォルトで Server Component です。async/await で直接データを取得できます。
// app/users/page.tsx
type User = {
id: number;
name: string;
email: string;
};
export default async function UsersPage() {
const res = await fetch("https://jsonplaceholder.typicode.com/users", {
next: { revalidate: 3600 }, // 1時間キャッシュ
});
const users: User[] = await res.json();
return (
<ul>
{users.map((user) => (
<li key={user.id}>
{user.name} ({user.email})
</li>
))}
</ul>
);
}
2. Server Actions(フォーム処理)
サーバー側で実行される関数をクライアントのフォームから直接呼び出せます。
// app/contact/page.tsx
export default function ContactPage() {
async function submitForm(formData: FormData) {
"use server";
const name = formData.get("name") as string;
const message = formData.get("message") as string;
// DB保存やメール送信などのサーバー処理
console.log(`Name: ${name}, Message: ${message}`);
}
return (
<form action={submitForm}>
<input type="text" name="name" placeholder="お名前" required />
<textarea name="message" placeholder="メッセージ" required />
<button type="submit">送信</button>
</form>
);
}
3. useRouter / <Link> によるクライアントサイドナビゲーション
// app/components/Navigation.tsx
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
export default function Navigation() {
const router = useRouter();
const handleClick = () => {
// プログラム的な遷移
router.push("/dashboard");
};
return (
<nav>
{/* 宣言的なナビゲーション(推奨) */}
<Link href="/">ホーム</Link>
<Link href="/about">About</Link>
<Link href="/blog" prefetch={false}>
ブログ
</Link>
{/* プログラム的なナビゲーション */}
<button onClick={handleClick}>ダッシュボードへ</button>
</nav>
);
}
4. Route Handlers(API エンドポイント)
app/api/ 配下に route.ts を配置すると REST API を作成できます。
// app/api/hello/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const name = searchParams.get("name") ?? "World";
return NextResponse.json({
message: `Hello, ${name}!`,
timestamp: new Date().toISOString(),
});
}
export async function POST(request: NextRequest) {
const body = await request.json();
// バリデーションやDB保存処理
return NextResponse.json(
{ success: true, data: body },
{ status: 201 }
);
}
5. Middleware(リクエストの前処理)
プロジェクトルートに middleware.ts を配置すると、リクエストをインターセプトできます。
// middleware.ts
import { NextRequest, NextResponse } from "next/server";
export function middleware(request: NextRequest) {
const token = request.cookies.get("auth-token")?.value;
// 認証が必要なパスで未認証ならリダイレクト
if (!token && request.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", request.url));
}
// レスポンスヘッダーの追加
const response = NextResponse.next();
response.headers.set("x-request-id", crypto.randomUUID());
return response;
}
export const config = {
matcher: ["/dashboard/:path*", "/api/:path*"],
};
類似パッケージとの比較
| 特徴 | Next.js | Remix | Nuxt | Astro |
|---|---|---|---|---|
| ベースライブラリ | React | React | Vue | フレームワーク非依存 |
| レンダリング方式 | SSR / SSG / ISR / CSR | SSR / CSR | SSR / SSG / CSR | SSG 中心(SSR可) |
| App Router | ✅ ファイルベース | ✅ ファイルベース | ✅ ファイルベース | ✅ ファイルベース |
| Server Components | ✅ | ✅(v2.x〜) | ❌(Vue の仕組み) | ✅(Islands) |
| デプロイ先 | Vercel / セルフホスト / 各種 | 各種 | Vercel / Nitro 対応先 | 各種 |
| エコシステム | 非常に大きい | 成長中 | Vue エコシステム | 成長中 |
| 学習コスト | 中〜高 | 中 | 中(Vue 経験者は低) | 低〜中 |
選定の目安:
- React でフルスタック → Next.js または Remix
- Vue を使いたい → Nuxt
- コンテンツサイト中心 → Astro
注意点・Tips
1. Server Component と Client Component の境界を意識する
// ❌ Server Component で useState は使えない
// app/page.tsx
import { useState } from "react"; // エラー!
export default function Page() {
const [count, setCount] = useState(0); // Server Component では不可
return <div>{count}</div>;
}
// ✅ クライアント側のインタラクションは "use client" を宣言
// app/components/Counter.tsx
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
原則: "use client" はできるだけ末端のコンポーネントに限定し、Server Component の恩恵(バンドルサイズ削減・直接データフェッチ)を最大化しましょう。
2. next.config.ts の型安全な設定
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "example.com",
},
],
},
experimental: {
// 実験的機能はここに
},
};
export default nextConfig;
3. 画像最適化は next/image を必ず使う
import Image from "next/image";
// ✅ 自動で WebP/AVIF 変換、遅延読み込み、サイズ最適化
<Image
src="/hero.jpg"
alt="ヒーロー画像"
width={1200}
height={630}
priority // LCP 対象の画像には priority を付与
/>
<img> タグを直接使うと最適化が効かないため、特別な理由がない限り next/image を使いましょう。
4. キャッシュ戦略を理解する
Next.js のキャッシュは多層構造です。意図しないキャッシュでハマることが多いポイントです。
// キャッシュなし(毎回フェッチ)
fetch(url, { cache: "no-store" });
// 一定時間キャッシュ(ISR 的な挙動)
fetch(url, { next: { revalidate: 60 } });
// タグベースのオンデマンド再検証
import { revalidateTag } from "next/cache";
fetch(url, { next: { tags: ["posts"] } });
// 任意のタイミングで再検証
revalidateTag("posts");
5. Pages Router と App Router の混在に注意
既存プロジェクトでは pages/ と app/ が混在する場合があります。同じパスが両方に存在するとビルドエラーになります。移行は段階的に行いましょう。
まとめ
Next.js は、React アプリケーションを本番運用するための事実上の標準フレームワークです。App Router と Server Components により、サーバーとクライアントの責務を明確に分離しながら、高パフォーマンスなアプリケーションを構築できます。エコシステムが非常に充実しているため、認証・CMS・データベースなど周辺ツールとの統合もスムーズに進められるでしょう。