Next.js 入門と2026年の現在地 —— React経験者・サーバーサイド出身者のための整理
結論から
- Next.jsは「Reactでプロダクションを作るための標準フレームワーク」。ルーティング、SSR/SSG、画像・フォント最適化、APIサーバー機能が最初から入っている。
- 2026年8月時点の最新は16系(16.3.0が2026年8月リリース)。13〜15で積み上げたApp Routerが、16でようやく「一貫した設計」に落ち着いた印象。
- 16の変更点は大きく4つ。Turbopackがデフォルト / キャッシュが完全オプトイン(Cache Components) /
middleware.ts→proxy.ts/ React 19.2対応。 - 今から学ぶならApp Router一本でいい。Pages Routerは既存プロジェクトの保守用と割り切る。
1. そもそもNext.jsは何を解決しているのか
React単体は「UIを描画するライブラリ」でしかない。実務でアプリを作ろうとすると、以下を自前で用意する必要がある。
- ルーティング(React Router等)
- SSR/SSGによるSEO対応
- バンドラ設定(Vite/webpack)
- 画像・フォントの最適化
- APIエンドポイント(別途Express等)
Next.jsはこれを全部入りで、設定なしで提供する。Laravelが「PHPでWebアプリを作るための一式」であるのと同じ位置づけと考えると分かりやすい。
サーバーサイド出身者向けの対応表
| やりたいこと | Laravel | Next.js (App Router) |
|---|---|---|
| ルーティング | routes/web.php |
app/ 配下のディレクトリ構造 |
| コントローラ | app/Http/Controllers |
Server Component / Route Handler |
| Blade テンプレート | resources/views |
page.tsx(React Server Component) |
| 共通レイアウト | @extends('layouts.app') |
layout.tsx(ネスト可) |
| ミドルウェア | app/Http/Middleware |
proxy.ts(旧 middleware.ts) |
| フォーム送信 → DB更新 | POSTルート + コントローラ | Server Actions |
| キャッシュ | Cache::remember() |
"use cache" + cacheTag
|
| バリデーション | FormRequest | Zod等を自前で(標準機能なし) |
| ORM | Eloquent | Prisma / Drizzle 等を別途 |
Next.jsはフルスタックを名乗るがバックエンドは薄い。ORM・認証・バリデーションは自分で選ぶ。ここがLaravelとの一番大きな違いで、「Laravel(API) + Next.js(フロント)」という構成も現役で普通に採用される。
2. App Router の基本
app/ ディレクトリの構造がそのままURLになる。
app/
├── layout.tsx → 全ページ共通レイアウト
├── page.tsx → /
├── jobs/
│ ├── page.tsx → /jobs
│ ├── loading.tsx → ローディングUI(自動でSuspense境界)
│ ├── error.tsx → エラーUI(自動でError Boundary)
│ └── [id]/
│ └── page.tsx → /jobs/123
└── api/
└── health/
└── route.ts → GET /api/health
特徴的なのは loading.tsx と error.tsx。ファイルを置くだけでSuspense境界とError Boundaryが自動生成される。この「ファイル名が規約になる」感覚はLaravelのディレクトリ規約に近い。
3. Server Components が既定 —— ここが最大の思想転換
App Routerでは、何も書かなければそのコンポーネントはサーバーで動く。
// app/jobs/page.tsx —— これはServer Component
import { db } from '@/lib/db';
export default async function JobsPage() {
// ブラウザに一切送られないコード。DBを直接叩いてよい
const jobs = await db.job.findMany({ where: { published: true } });
return (
<ul>
{jobs.map((job) => (
<li key={job.id}>{job.title}</li>
))}
</ul>
);
}
useState やイベントハンドラが必要な箇所だけ、ファイル先頭に "use client" を書いてClient Componentにする。
'use client';
import { useState } from 'react';
export function SearchBox({ onSearch }: { onSearch: (q: string) => void }) {
const [q, setQ] = useState('');
return <input value={q} onChange={(e) => setQ(e.target.value)} />;
}
設計の原則は「Client Componentを葉っぱに追いやる」。ページ全体をClient Componentにしてしまうと、Next.jsを使う意味の半分が消える。
Server Actions
フォーム送信のためにAPIエンドポイントを作る必要がなくなった。
// app/jobs/new/page.tsx
import { redirect } from 'next/navigation';
import { db } from '@/lib/db';
export default function NewJobPage() {
async function createJob(formData: FormData) {
'use server'; // ← この関数はサーバーでのみ実行される
const title = String(formData.get('title'));
await db.job.create({ data: { title } });
redirect('/jobs');
}
return (
<form action={createJob}>
<input name="title" required />
<button type="submit">登録</button>
</form>
);
}
Laravelでいう「POSTルート + コントローラ + リダイレクト」が、関数1つに畳み込まれる。ただしServer Actionsは公開エンドポイントと同義なので、認可チェックはアクション内部で必ず行うこと。ここは事故が起きやすい。
4. Next.js 16 の目玉:Cache Components(キャッシュの完全オプトイン化)
13〜15で最も評判が悪かったのが「暗黙のキャッシュ」だった。fetch が勝手にキャッシュされ、開発中は動くのに本番でデータが更新されない、という事故が多発した。
16ではこれが逆転する。デフォルトは全部dynamic(キャッシュしない)。キャッシュしたいものだけ明示する。
// キャッシュしたい関数に "use cache" を付ける
import { cacheLife, cacheTag } from 'next/cache';
async function getJobCategories() {
'use cache';
cacheLife('hours'); // 有効期間のプリセット
cacheTag('categories'); // タグを付けて後で無効化できる
return db.category.findMany();
}
更新時はタグ単位で吹き飛ばす。
'use server';
import { updateTag } from 'next/cache';
export async function addCategory(name: string) {
await db.category.create({ data: { name } });
updateTag('categories'); // 該当キャッシュだけ無効化
}
Cache::tags(['categories'])->flush() とほぼ同じ発想。「暗黙より明示」に倒したのは正しい判断だと思う。
有効化は next.config.ts で。
const nextConfig = {
cacheComponents: true,
};
export default nextConfig;
注意点として、cacheComponents: true は単なるリネームではない。<Suspense> の外にキャッシュされていないデータ取得があるとビルドエラーになるので、既存アプリの移行は段階的にやったほうがいい。
5. middleware.ts → proxy.ts
16で middleware.ts は非推奨になり、proxy.ts にリネームされた。
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server';
export default function proxy(request: NextRequest) {
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*'],
};
理由は「Express.jsのmiddlewareと混同されやすい」「高機能すぎて濫用を招いた」から。公式は最後の手段として使えというスタンスに変わっている。
移行はcodemodで済む。
npx @next/codemod@canary upgrade latest
proxy.ts はNode.jsランタイム固定でEdgeでは動かない。Edgeが必要なら当面 middleware.ts を残す。
6. Turbopack がデフォルトに
Rust製バンドラのTurbopackが、開発・ビルドの両方で既定になった。webpack時代と比べてHMRとコンパイルが体感で明確に速い。
移行で詰まったら、フォールバックできる。
next build --webpack
まず --webpack でビルドが通ることを確認してから外す、という順番が安全。他に16ではNode.js 20.9以上が必須(18はサポート終了)、TypeScriptは5.1以上。
7. 採用判断:向く / 向かない
向いている
- SEOが売上に直結するサービス(求人・EC・メディア)
- 更新頻度が高いコンテンツを高速に配信したい
- フロントとバックの言語をTypeScriptに統一したい
- Vercelにそのまま乗せられる
慎重に
- 管理画面のみ、SEO不要 → React + Vite で十分。Next.jsは過剰
- 既存のLaravel/Railsが完成している → APIだけ残してフロントを載せ替える構成のほうが現実的
- チームにReactの実装者がいない → Server/Client Componentの境界設計でつまずく
- バージョンアップ追従のコストが払えない → 破壊的変更のペースは速い
8. 始め方
npx create-next-app@latest my-app
cd my-app
npm run dev
TypeScript / Tailwind CSS / App Router を全部Yesで選んでおけば、2026年時点の標準構成になる。
最初に手を動かすなら、この順番がおすすめ。
-
app/にページを2〜3枚足してルーティングを体感する - Server Componentから直接DB(またはfetch)を叩く
-
"use client"が必要になる箇所を実際に踏んで境界を理解する - Server Actionsでフォーム送信を書く
- 最後に
"use cache"でキャッシュを足す
キャッシュは最後でいい。動くものを作ってから最適化したほうが、16の設計思想も理解しやすい。