Next.js: Next.js 16 入門
Next.js 16 は、Vercel によるフルスタック React フレームワークの最新バージョンです。ファイルシステムルーティング、サーバーサイドレンダリング、静的生成、増分静的再生成、部分プリレンダリングを単一の開発フレームワークに統合し、フルスタック開発をシンプルにします。
このチュートリアルは、React の基礎知識を持つフロントエンド開発者向けに設計されています。App Router の基本から始めて、Next.js 16 で本番環境対応のフルスタックアプリケーションを構築するところまで進みます。
1. 学習内容
- Next.js とは何か、なぜ選ぶのか?
- App Router と Pages Router の進化
- Next.js 16 の 5 つのコア機能:Turbopack / PPR /
use cache/ React 19 / Proxy - 4 世代のレンダリング戦略の進化:SSR、SSG、ISR、PPR
- Next.js と Remix、Nuxt、Astro の比較
2. あるフルスタック開発者の実話
(1) 課題:React SPA プロジェクトのパフォーマンスボトルネック
Alice は SaaS 企業のフルスタック開発者で、5 万人のデイリーアクティブユーザーを抱える React SPA のタスク管理プラットフォームを保守しています。最近、彼女は 3 つの困難な問題に直面しました:
| 問題 | 影響 | データ |
|---|---|---|
| 初回画面の読み込みが遅い | 高い直帰率 | 3.2s FCP / 6.8s LCP |
| SEO が悪い | Google が動的コンテンツをインデックスできない | 検索結果 0 件 |
| コード再利用性が低い | フロントエンドとバックエンドで別々のデータロジック | 40% コード重複 |
彼女は React Helmet、遅延読み込み、コード分割を試しましたが、純粋な SPA アーキテクチャでは SEO の問題を解決できませんでした。
(2) Next.js による解決策
Next.js 16 App Router を使ってアプリを書き直す — サーバーコンポーネントによるサーバーサイドレンダリング + PPR 静的シェル +
use cacheスマートキャッシング。
// app/dashboard/page.tsx — サーバーコンポーネント(デフォルト)
export default async function DashboardPage() {
const tasks = await fetch('https://api.example.com/tasks');
const projects = await fetch('https://api.example.com/projects');
return (
<div className="grid grid-cols-2 gap-4">
<TaskSummary tasks={tasks} />
<ProjectList projects={projects} />
</div>
);
}
(3) 成果
| 指標 | 改修前(React SPA) | 改修後(Next.js 16) |
|---|---|---|
| FCP | 3.2s | 0.8s |
| LCP | 6.8s | 1.5s |
| SEO ページ数 | 0 | 200+ |
| コード重複率 | 40% | 5% |
3. Next.js とは?
(1) 定義
Next.js は、React ベースのフルスタック Web 開発フレームワークで、2016 年に Vercel によってオープンソース化されました。ファイルシステムルーティング、サーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、API ルーティングなどの機能をすぐに利用でき、開発者は React を使ってフルスタックアプリケーションを構築できます。
graph TB
A[Next.js 16] --> B[App Router<br/>ファイルシステムルーティング]
A --> C[レンダリングエンジン<br/>SSR/SSG/ISR/PPR]
A --> D[データ取得<br/>サーバーコンポーネント]
A --> E[API ルート<br/>Route Handlers]
A --> F[ビルドツール<br/>Turbopack]
A --> G[エコシステム統合<br/>認証/DB/キャッシュ]
style A fill:#cce5ff
style B fill:#d4edda
style C fill:#d4edda
| コア機能 | 説明 | 解決する問題 |
|---|---|---|
| ファイルシステムルーティング | ファイル名が URL パスになる | 手動ルーティング設定不要 |
| サーバーコンポーネント | クライアント JavaScript ゼロのサーバーサイドレンダリング | バンドルサイズ削減 |
| PPR | 静的シェル + 動的コンテンツストリーミング | SEO とパーソナライゼーションの両立 |
| Turbopack | Rust 製インクリメンタルビルド | 開発サーバーが 10 倍高速 |
use cache |
宣言的コンポーネントレベルキャッシング | きめ細かなキャッシュ制御 |
(2) Next.js を選ぶ理由
- フルスタック統合:フロントエンド + API + データ取得を 1 つのフレームワークで
- React 公式推奨:React ドキュメントが Next.js を推奨フレームワークとして掲載
- Vercel エコシステム:デプロイ、分析、AI のシームレス統合
- 大手企業の支持:Vercel(評価額 30 億ドル)、TikTok、Notion が採用
▶ サンプル: Next.js 16 プロジェクトの作成と実行
図:Next.js 16; App Router ファイルシステムルーティング; レンダリングエンジン SSR/SSG/ISR/PPR; データ取得 サーバーコンポーネント; API ルート Route Handlers; ビルドツール Turbopack
# 1. create-next-app でプロジェクト作成(推奨)
npx create-next-app@latest my-next-app --ts --tailwind --app
# 2. プロジェクトディレクトリに移動
cd my-next-app
# 3. 開発サーバーを起動(Turbopack デフォルト)
npm run dev
# 4. ターミナル出力の抜粋
▲ ▲ ▲ ▲ ▲ ▲
▲ Next.js 16.2.10 (Turbopack)
▲ Local: http://localhost:3000
▲ Environments: .env.local
▲ Next.js 16.2.10
- Local: http://localhost:3000
✓ Ready in 876ms (Turbopack)
開発サーバーが http://localhost:3000 で起動中です。ブラウザでこの URL を開くと、Next.js のデフォルトウェルカムページが表示されます。
▶ サンプル: Next.js ページで何ができるか?
// app/page.tsx — 1ページ = データ取得 + レンダリング + インタラクション
export default async function HomePage() {
const data = await fetch('https://jsonplaceholder.typicode.com/posts/1');
return (
<main>
<h1 className="text-2xl font-bold">Welcome to Next.js 16</h1>
<p>サーバーでレンダリングされたコンテンツ: {data.title}</p>
</main>
);
}
<h1>Welcome to Next.js 16</h1>
<p>サーバーでレンダリングされたコンテンツ: sunt aut facere repellat provident</p>
ブラウザに表示される内容:「Welcome to Next.js 16」という見出しと、API から取得したサーバーサイドレンダリングコンテンツ — データはサーバーで取得され、事前レンダリングされた HTML として配信されます。
4. Pages Router から App Router へ
(1) 歴史的発展
timeline
title Next.js ルーティングシステムの進化
2016 : Next.js 1.0 リリース Pages Router
2019 : 9.3 SSG + getStaticProps 対応
2021 : 12 リリース、React 18 + Rust コンパイラ
2022 : 13 リリース、App Router ベータ (RSC)
2023 : 14 App Router 安定版、Turbopack ベータ
2025 : 15 App Router デフォルト、React 19
2026 : 16 Turbopack デフォルト、PPR 安定版、use cache
| バージョン | ルーティングシステム | データ取得方法 | レンダリングモード |
|---|---|---|---|
| v1-v12 | Pages Router | getServerSideProps / getStaticProps |
SSR / SSG |
| v13-v14 | Pages + App Router(オプション) | RSC + fetch |
SSR / SSG / ISR |
| v15 | App Router(デフォルト) | RSC + Server Actions | SSR / SSG / ISR / PPR |
| v16 | App Router(専用) | RSC + use cache |
SSR / SSG / ISR / PPR |
(2) App Router のコア概念モデル
App Router の重要な変更点は、コンポーネントがデフォルトでサーバー上で実行されることです。
// Pages Router 旧モデル (v12)
export async function getServerSideProps() {
return { props: { data: await fetchData() } };
}
export default function Page({ data }) {
return <div>{data}</div>; // すべてのコードがクライアントサイド
}
// App Router 新モデル (v16)
export default async function Page() {
const data = await fetchData(); // コンポーネント内で直接取得
return <div>{data}</div>; // デフォルトのサーバーコンポーネント
}
▶ サンプル: Pages Router と App Router のコード比較
Page コンポーネントの UI をレンダリングします。
// ============================================
// Pages Router (pages/posts/[id].tsx)
// getServerSideProps の追加エクスポートが必要
// ============================================
export async function getServerSideProps({ params }) {
const res = await fetch(`https://api.example.com/posts/${params.id}`);
return { props: { post: await res.json() } };
}
export default function PostPage({ post }) {
return <h1>{post.title}</h1>;
}
// ============================================
// App Router (app/posts/[id]/page.tsx)
// 直接 async コンポーネント、追加エクスポート不要
// ============================================
export default async function PostPage({ params }) {
const post = await fetch(`https://api.example.com/posts/${params.id}`);
return <h1>{post.title}</h1>;
}
Pages Router: 18 行のコード(getServerSideProps 含む)
App Router: 8 行のコード(直接 async コンポーネント)
サンプルコード 55% 削減
App Router はボイラープレートを 55% 削減:getServerSideProps 不要、直接 async コンポーネント、コンポーネント本体内での自動データ取得。
5. Next.js 16 の新機能概要
(1) 5 つのコア機能
graph LR
A[Next.js 16] --> B[Turbopack デフォルト<br/>開発とビルドが 10 倍高速]
A --> C[PPR 安定版<br/>部分プリレンダリング]
A --> D[use cache<br/>宣言的キャッシング]
A --> E[React 19<br/>Actions + use()]
A --> F[Proxy API<br/>ミドルウェアの一部を置き換え]
A --> G[after()<br/>レスポンス後タスク]
style A fill:#cce5ff
style B fill:#d4edda
| 機能 | 状態 | 開発者へのメリット |
|---|---|---|
| Turbopack デフォルト | 安定版 | 開発ビルドが 10 倍高速、HMR 即時更新 |
| 部分プリレンダリング | 安定版 | 静的シェル SEO + 動的コンテンツパーソナライゼーション |
use cache |
安定版 | コンポーネントレベルキャッシング、getStaticProps を置き換え |
| React 19 | 組み込み | Server Actions、use()、useOptimistic |
| Proxy API | 新機能 | サーバーサイドプロキシ転送、ミドルウェアの一部を置き換え |
| after() | 新機能 | レスポンス後の非同期タスク(ログ記録/分析) |
(2) Turbopack デフォルトビルド
Turbopack は Vercel が Rust で開発したインクリメンタルバンドルツールで、Next.js 16 ではデフォルトで有効です。
| 比較項目 | Webpack (v15) | Turbopack (v16) |
|---|---|---|
| コールドスタート | 5~10 s | 0.5~1 s |
| HMR ホットリロード | 50~200 ms | < 10 ms |
| ビルド速度 | ベースライン | 10 倍高速 |
| 設定レベル | 複雑 | ゼロ設定 |
▶ サンプル: Turbopack の即時ホットアップデート体験
# Next.js 16 開発サーバー起動、デフォルトで Turbopack 使用
npm run dev
# コンソール出力
▲ ▲
▲ Next.js 16.2
▲ - Local: http://localhost:3000
▲ - Turbopack (experimental): ✓ loaded in 876ms
# 任意のファイルを編集して保存 — 即時ホットフィックス
✔ Updated /app/page.tsx in 3ms
Turbopack 起動時間: 876ms
ホットフィックス適用時間: 3ms
比較 Webpack コールドスタート: 5-10s
Turbopack HMR: ファイル更新あたり 4ms(対 Webpack 50-200ms)。コールドスタート: 876ms(対 5-10s)。大規模プロジェクトビルド: 全体で 10 倍高速。
(3) 部分プリレンダリング(PPR)
PPR は Next.js 16 の最も重要な革新です。ページの静的部分を HTML として事前レンダリングし、動的部分は Suspense 境界を通じてストリーミングされます。
graph TB
subgraph PPR ページ
A[静的シェル<br/>事前レンダリング HTML] --> B[ナビゲーションバー]
A --> C[サイドバー]
A --> D[Suspense 境界<br/>---]
D --> E[動的コンテンツ<br/>ストリーミングレンダリング]
D --> F[ユーザーデータ<br/>ストリーミングレンダリング]
end
style A fill:#d4edda
style D fill:#f8d7da
| レンダリング戦略 | ビルド時 | リクエスト時 | キャッシング | SEO |
|---|---|---|---|---|
| SSR | ❌ | ✅ 完全レンダリング | ❌ | ✅ |
| SSG | ✅ 完全事前レンダリング | ❌ | ✅ | ✅ |
| ISR | ✅ 完全事前レンダリング | ✅ オンデマンド再生成 | ✅ | ✅ |
| PPR | ✅ 静的シェル | ✅ 動的部分ストリーミング | ✅ | ✅ |
(4) use cache 宣言的キャッシング
// app/page.tsx — use cache ディレクティブの使用
import { unstable_cache as cache } from 'next/cache';
export default async function Page() {
const data = await getData();
return <div>{JSON.stringify(data)}</div>;
}
const getData = cache(
async () => {
return fetch('https://api.example.com/expensive-data');
},
['expensive-data'],
{ revalidate: 3600 }
);
▶ サンプル: PPR + use cache の実践的組み合わせ
データを取得し、結果をレンダリングします。
// ============================================
// PPR 静的シェル + use cache スマートキャッシング
// ホーム = 静的ヘッダー + 動的コンテンツ推奨(1時間キャッシュ)
// ============================================
// app/page.tsx
import { Suspense } from 'react';
import { RecommendedProducts } from './RecommendedProducts';
export default function HomePage() {
return (
<div>
<header className="bg-gray-100 p-4">
<h1>Welcome to ShopHub</h1>
<nav>Categories | Deals | Support</nav>
</header>
{/* PPR 境界: 動的コンテンツ推奨 */}
<Suspense fallback={<div className="animate-pulse h-40 bg-gray-200" />}>
<RecommendedProducts />
</Suspense>
</div>
);
}
静的シェルが即座にレンダリングされ、動的コンテンツが Suspense 境界内で読み込まれます。
表示テキスト: Welcome to ShopHub | Categories | Deals | Support
// app/RecommendedProducts.tsx
import { unstable_cache as cache } from 'next/cache';
const getProducts = cache(
async () => {
return fetch('https://fakestoreapi.com/products?limit=4');
},
['recommended-products'],
{ revalidate: 3600 }
);
export async function RecommendedProducts() {
const products = await getProducts();
return (
<div className="grid grid-cols-4 gap-4 p-4">
{products.map(p => (
<div key={p.id} className="border rounded p-2">
<img src={p.image} alt={p.title} className="h-32" />
<p className="font-bold">{p.title}</p>
<p>${p.price}</p>
</div>
))}
</div>
);
}
ページ読み込み時の動作:
1. 静的ヘッダー(ナビゲーションバー)が即座に表示
2. 推奨エリアにスケルトンスクリーン(灰色プレースホルダーアニメーション)を表示
3. データ準備完了後、4 つの商品カードをストリーミングレンダリング
4. 同一ユーザーが 1 時間以内に再訪問した場合はキャッシュから提供、fetch 不要
(5) React 19 との深い統合
Next.js 16 は React 19 を組み込みで提供し、以下をサポートします:
- Server Actions:
'use server'で関数をバックエンドで直接実行 use()Hook: レンダリング中に Promise を読み取るuseOptimistic: 楽観的 UI 更新useFormStatus: フォーム送信状態
▶ サンプル: React 19 Server Actions 簡易フォーム
上記の説明に従ってページがレンダリングされ、説明された動作に基づいて UI が更新されます。
// ============================================
// Server Action: フォーム送信が直接バックエンド関数を呼び出す
// API Route を手動で作成する必要なし
// ============================================
// app/contact/page.tsx
export default function ContactPage() {
async function handleSubmit(formData) {
'use server';
const name = formData.get('name');
const email = formData.get('email');
// データベースに直接書き込むか、メールを送信
console.log(`New contact: ${name} <${email}>`);
// 成功ページにリダイレクト
redirect('/contact/success');
}
return (
<form action={handleSubmit}>
<input name="name" placeholder="Your name" required />
<input name="email" type="email" placeholder="Your email" required />
<button type="submit">Send</button>
</form>
);
}
入力フィールドと送信ボタンのあるフォーム。
送信時、Server Action がデータを処理し、成功ページにリダイレクトします。
フォーム送信後の動作:
1. handleSubmit 関数がサーバー上で実行される
2. formData がフォームフィールドを自動収集
3. redirect がサーバー 303 リダイレクトを実行
4. API Route / fetch コードの記述不要
6. フレームワーク比較: Next.js vs Remix vs Nuxt vs Astro
(1) 4 フレームワークの位置付け
graph TB
subgraph "フルスタックフレームワーク"
A[Next.js<br/>React エコシステム] --> B[Remix<br/>Web 標準第一]
C[Nuxt<br/>Vue エコシステム]
end
subgraph "静的サイト"
D[Astro<br/>マルチフレームワーク Islands]
end
style A fill:#cce5ff
style C fill:#d4edda
(2) 詳細比較
| 次元 | Next.js 16 | Remix 2 | Nuxt 4 | Astro 5 |
|---|---|---|---|---|
| ベースフレームワーク | React 19 | React 18 | Vue 3 / Nitro | 任意(Islands) |
| ルーティング方式 | ファイルシステム(App Router) | ファイルシステム | ファイルシステム | ファイルシステム |
| レンダリングモード | SSR/SSG/ISR/PPR | SSR/SSG | SSR/SSG/ISR | SSG(デフォルト)/ SSR |
| PPR | ✅ 安定版 | ❌ | ❌ | ❌ |
| サーバーコンポーネント | ✅ デフォルト | ❌ | ❌ | ❌ |
use cache |
✅ 安定版 | ❌ | ❌ | ❌ |
| Turbopack | ✅ デフォルト | ❌ | Vite | Vite |
| ビルド速度 | 10x(Turbopack) | 1x | 1x | 1x |
| データ取得 | RSC + fetch | loader + action | asyncData | 組み込みなし |
| API ルート | Route Handlers | action + resource | server routes | なし |
| 学習曲線 | 中(React 必須) | 中(Web 標準必須) | 中(Vue 必須) | 低(任意) |
| スター | 130k⭐ | 30k⭐ | 55k⭐ | 50k⭐ |
| デプロイプラットフォーム | Vercel + 任意 | Fly + 任意 | Vercel + 任意 | Netlify + 任意 |
(3) 選択推奨
| シナリオ | 推奨フレームワーク | 理由 |
|---|---|---|
| フルスタック SaaS アプリ | Next.js 16 | PPR + RSC + Server Actions: 最善 |
| コンテンツ重視のサイト/ブログ | Astro | JS ゼロ出力、究極のパフォーマンス |
| Web 標準第一 | Remix | HTTP 仕様と FormData に準拠 |
| Vue 技術スタック | Nuxt | Vue エコシステムの自然な拡張 |
| EC/ダッシュボード | Next.js 16 | PPR 静的シェル + 動的データ分離 |
| 静的ドキュメントサイト | Astro | Islands アーキテクチャ + ネイティブ MDX 対応 |
7. ユースケースと選択推奨
(1) Next.js 16 のユースケース
| シナリオ | 説明 | 代表的な顧客 |
|---|---|---|
| SaaS プラットフォーム | ダッシュボード + マルチテナント + リアルタイムデータ | Notion, Linear |
| EC サイト | 商品カタログ(SSG) + ショッピングカート(SSR) | TikTok Shop |
| コンテンツプラットフォーム | 記事(ISR) + 推奨(ストリーミング) | Medium |
| 管理パネル | PPR 静的シェル + 動的ウィジェット | Vercel ダッシュボード |
| AI アプリケーション | ストリーミングテキスト生成 + SSE | Vercel AI SDK |
(2) 適さない状況
- 純粋な静的ブログ(Astro のほうが軽量)
- シンプルなランディングページ(プレーンな HTML/CSS で十分)
- ネイティブモバイルアプリ(React Native / Flutter)
8. 完全な例: 複数のレンダリング戦略を組み合わせたページ
// ============================================
// 総合例: EC 商品詳細ページ
// 機能: SSG 静的ディレクトリ + PPR 推奨 + ISR コメント
// ============================================
// app/products/[id]/page.tsx
import { Suspense } from 'react';
import { notFound } from 'next/navigation';
// 静的ページパラメータ生成(ビルド時に事前生成)
export async function generateStaticParams() {
const products = await fetch('https://fakestoreapi.com/products');
const ids = await products.json();
return ids.map(p => ({ id: String(p.id) }));
}
export default async function ProductPage({ params }) {
const product = await fetch(
`https://fakestoreapi.com/products/${params.id}`
);
if (!product) {
notFound();
}
return (
<div className="container mx-auto p-4">
{/* 静的セクション: 基本商品情報 */}
<div className="flex gap-8">
<img src={product.image} alt={product.title} className="w-64 h-64" />
<div>
<h1 className="text-2xl font-bold">{product.title}</h1>
<p className="text-xl text-green-600">${product.price}</p>
<p className="mt-4">{product.description}</p>
</div>
</div>
{/* PPR 動的境界: 推奨商品 */}
<Suspense fallback={<div>Loading recommendations...</div>}>
<Recommendations category={product.category} />
</Suspense>
{/* ISR コメントセクション: 毎時間再生成 */}
<Suspense fallback={<div>Loading reviews...</div>}>
<Reviews productId={params.id} />
</Suspense>
</div>
);
}
// app/products/[id]/Recommendations.tsx
async function Recommendations({ category }) {
const products = await fetch(
`https://fakestoreapi.com/products/category/${category}`
);
return (
<div className="mt-8">
<h2 className="text-xl font-bold">推奨商品</h2>
<div className="grid grid-cols-4 gap-4 mt-4">
{products.slice(0, 4).map(p => (
<div key={p.id} className="border p-2 rounded">{p.title}</div>
))}
</div>
</div>
);
}
// app/products/[id]/Reviews.tsx
async function Reviews({ productId }) {
const reviews = await fetch(
`https://api.example.com/reviews/${productId}`,
{ next: { revalidate: 3600 } }
);
return (
<div className="mt-8">
<h2 className="text-xl font-bold">カスタマーレビュー</h2>
{reviews.map(r => (
<div key={r.id} className="border-b py-2">
<p className="font-bold">{r.author}</p>
<p>{r.content}</p>
</div>
))}
</div>
);
}
1. 商品基本情報が即座に表示(SSG 静的 HTML)
2. 推奨エリアに「Loading recommendations...」プレースホルダーを表示
3. コメントセクションに「Loading reviews...」プレースホルダーを表示
4. 推奨コンテンツのストリーミングレンダリング(PPR)
5. キャッシュされたコメントコンテンツを 1 時間後に必要に応じて更新(ISR)
6. ページ全体に完全な SEO メタデータ
❓ よくある質問
use()、useOptimistic)が Next.js で利用可能です。React を別途インストールする必要はなく、npm create-next-app が自動的に適合バージョンをインストールします。output: 'standalone' モードは独立したディレクトリを出力でき、Docker のマルチステージビルドと Nginx リバースプロキシを組み合わせることで、セルフホストデプロイが可能です。📖 まとめ
- Next.js 16 は Vercel が開発したフルスタック React フレームワークで、ファイルシステムルーティング、レンダリングエンジン、API ルーティングを提供します
- App Router が Pages Router を置き換え、サーバーコンポーネントがデフォルトでサーバー上で実行され、クライアント JavaScript のサイズを削減します
- 5 つの主要新機能:Turbopack(10 倍高速ビルド)、PPR(部分プリレンダリング)、
use cache(宣言的キャッシング)、React 19、Proxy API - SSR、SSG、ISR、PPR の 4 世代のレンダリング戦略が、純粋な静的から完全な動的までの全範囲をカバーします
- Remix、Nuxt、Astro と比較して、Next.js 16 の独自の強みは PPR、サーバーコンポーネント、Turbopack です
- Next.js 16 はフルスタック SaaS、EC、コンテンツプラットフォームに適しています。純粋な静的サイトには Astro を推奨します
- PPR のコア概念は「静的シェル + 動的ストリーミング」— ナビゲーションバーのような不変要素は事前レンダリングされ、ユーザーデータのような可変要素は境界ベースでストリーミングされます
📝 練習問題
-
基本問題(⭐): Next.js 16 の公式ホームページ(nextjs.org)を読み、Next.js の 3 つのコア原則を自分の言葉で説明してください(50 文字以内)。
-
発展問題(⭐⭐):
create-next-appを使って新規プロジェクトを作成し(npx create-next-app@latest my-app --ts --tailwind)、開発サーバーを起動して、コンソール出力のスクリーンショットを撮り、Turbopack の起動時間をハイライトしてください。 -
挑戦問題(⭐⭐⭐): 以前に React SPA で構築した(またはよく知っている)プロジェクトを 1 つ選び、Next.js 16 で書き直す場合、どの部分を SSG、どの部分を SSR、どの部分を PPR にすべきか分析してください。200 文字以内の移行計画を書いてください。