4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

備忘録:今さらNext.jsの全体像を整理する。App Router・RSC・Server Actions・キャッシュがどう噛み合うのか(Next.js 16 / React 19)

4
Last updated at Posted at 2026-08-22

はじめに

Next.jsは、いまさら紹介するまでもないほど定着したスタックです。
入門記事も公式ドキュメントの和訳も出尽くしていて、「Next.jsとは何か」を新しく書く余地はほとんどありません。

それでも全体像を書き出そうと思ったのは、機能を個別に使えることと、全体を1枚で説明できることが別物だったからです。

App Router、Server Components、Server Actions、Route Handlers、キャッシュと再検証。
どれも触ったことはありますし、必要な場面では書けます。
ただ「これらがどう噛み合っているのか」「なぜこの機能がここにあるのか」を人に説明しようとすると、途端に言葉に詰まりました。

Reactだけでも画面は作れますが、実際のWebアプリケーションには画面以外の機能が必要です。

URLと画面を対応させるルーティング
サーバーからのデータ取得
フォームやデータ更新
APIエンドポイント
HTMLの事前生成
キャッシュと再検証
画像・フォントの最適化
SEO用メタデータ
エラーハンドリング
本番ビルドとデプロイ

Next.jsはこれらをReactと統合された形で提供します。
ばらばらに覚えていた機能が、この一覧のどこに対応するのかを整理し直したのが本記事です。

新しい発見を書いた記事ではありません。
既知のものを抜けなく1つの地図へ並べ直しただけの、自分用の棚卸しです。

環境は Next.js 16(App Router)/ React 19 / TypeScript を前提にしていて、内容は2026年8月時点のものです。
Next.js はキャッシュモデルやファイル規約がバージョンごとに変わるので、最終的な確認はそのつど利用中のバージョンの公式ドキュメントで行います。
掲載するコードは全体像を示すための最小例で、実務では認証・入力検証・エラー処理を別途足す必要があります。
参照元は記事末に列挙しました。

1. ReactとNext.jsの関係

Reactは、ユーザーインターフェースをコンポーネントとして構築するためのライブラリです。

'use client'

import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount((value) => value + 1)}>
      {count}
    </button>
  )
}

Reactが主に担当するのは、次の領域です。

  • コンポーネント
  • Props
  • State
  • イベント処理
  • Reactツリーの更新
  • Hooks
  • 宣言的なUI構築

一方、Reactだけではアプリケーション全体の構成方法は決まりません。

例えば、React単体では次の選択を開発者が行います。

ルーターは何を使うか
データ取得はどうするか
SSRをどう実装するか
APIサーバーを別に作るか
画像をどう最適化するか
ビルドとデプロイをどうするか

Next.jsは、これらに対する標準的な仕組みを提供します。

React
  → UIを構築する基盤

Next.js
  → Reactを使ってWebアプリケーション全体を構築する枠組み

したがって、Next.jsはReactの代替ではありません。

Next.jsの中でReactを使う

という関係です。

2. Next.jsが提供する主な機能

Next.jsの主要機能を整理すると、次のようになります。

領域 Next.jsが提供するもの
ルーティング ファイルシステムベースのApp Router
UI構築 React、Server Components、Client Components
データ取得 Server Componentからの直接取得、fetch統合
データ更新 Server Functions / Server Actions
HTTP API Route Handlers
レンダリング 静的生成、動的生成、ストリーミング
ナビゲーション <Link>、プリフェッチ、クライアント遷移
キャッシュ データ単位・ルート単位のキャッシュ機構(Cache Components を有効にするとコンポーネント単位も)
SEO Metadata API、OG画像、サイトマップ
最適化 Image、Font、Scriptの最適化
エラー処理 error.tsxnot-found.tsxなど
開発環境 開発サーバー、HMR、Turbopack、TypeScript統合
デプロイ Vercel、Node.js、Docker、静的書き出し、各種アダプター

つまりNext.jsは、単なる「Reactのビルドツール」ではありません。

UIフレームワーク
+
サーバー実行環境
+
ルーター
+
ビルドシステム
+
最適化機構

を組み合わせたアプリケーションフレームワークです。

3. Next.jsは「SSR専用フレームワーク」ではない

Next.jsは、よく「ReactをSSRするためのフレームワーク」と説明されます。

これは完全な間違いではありませんが、現在のApp Routerを説明するには不十分です。

ここで自分が混同していたのは、性質の違う軸を1列に並べてしまっていたことでした。
次の4つは排他的な選択肢ではなく、それぞれ別の軸です。

1. 生成時点
   ビルド時・再検証時のプリレンダリング / リクエスト時の動的レンダリング

2. コンポーネント境界
   Server Component / Client Component

3. 配信方法
   一括送信 / Streaming

4. 遷移方法
   初回のドキュメント取得 / クライアント側ナビゲーション

Server Component はビルド時にプリレンダリングされることも、リクエスト時に動的レンダリングされることもあります。
Client Component も初回アクセス時はHTML生成に使われ、そのあとブラウザで Hydration されます。
つまり「Server Component か Client Component か」と「静的か動的か」は別の軸です。

そのため、Next.jsを次のどれか一つとして捉えるのは正確ではありません。

SSRフレームワークだけ
SPAフレームワークだけ
静的サイトジェネレーターだけ
バックエンドフレームワークだけ

実際には、上の4軸をルート単位で組み合わせます。

4. App Routerとは

現在のNext.jsでは、appディレクトリを使うApp Routerが中心です。

URL構造をファイルとフォルダで表現します。

app/
├── layout.tsx
├── page.tsx
├── about/
│   └── page.tsx
└── products/
    ├── page.tsx
    └── [id]/
        └── page.tsx

対応するURLは次のとおりです。

app/page.tsx
  → /

app/about/page.tsx
  → /about

app/products/page.tsx
  → /products

app/products/[id]/page.tsx
  → /products/123

基本的な特殊ファイル

ファイル 役割
page.tsx そのURLで表示するページ
layout.tsx 複数ページで共有するレイアウト
loading.tsx 読み込み中のUI
error.tsx 予期しないエラーのUI
not-found.tsx 404相当のUI
route.ts HTTPリクエストを処理するRoute Handler
template.tsx 遷移時に再生成されるレイアウト相当のUI
default.tsx Parallel Routesのフォールバック
global-error.tsx ルートレイアウトの例外を表示するグローバルなエラーUI

error.tsx はそのセグメント配下の未処理例外を捕捉するClient Componentです。
同じセグメントの layout.tsx 自身で起きたエラーは捕捉しないため、ルートレイアウトのエラーには global-error.tsx を使います。

なお proxy.ts(Next.js 15 までの middleware.ts)は app 配下の特殊ファイルではありません。
プロジェクトルート、または src を使う場合は src 直下に1つだけ置き、apppages と同じ階層に配置します。

最小のページ

// app/page.tsx
export default function HomePage() {
  return (
    <main>
      <h1>Home</h1>
    </main>
  )
}

ルートレイアウト

// app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Sample App',
  description: 'Next.js sample application',
}

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="ja">
      <body>{children}</body>
    </html>
  )
}

layout.tsxはページ遷移をまたいで共有されます。

例えば、ヘッダー、サイドバー、ナビゲーション、Providerなどを配置できます。

5. Server ComponentとClient Component

App Routerでは、コンポーネントはデフォルトでServer Componentとして扱われます。

Server Component

// app/products/page.tsx
import { db } from '@/lib/db'

export default async function ProductsPage() {
  const products = await db.product.findMany()

  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  )
}

Server Componentでは、サーバー上で次の処理を実行できます。

  • DBアクセス
  • ファイル読み取り
  • 秘密情報を使った外部APIアクセス
  • サーバー専用ライブラリの利用
  • 表示に必要なデータ取得

Server Componentの実装コードは、そのままブラウザ用JavaScriptとして送る必要がありません。

Client Component

ユーザー操作やブラウザ状態が必要な場合は、ファイルの先頭に'use client'を書きます。

'use client'

import { useState } from 'react'

export function FavoriteButton() {
  const [favorite, setFavorite] = useState(false)

  return (
    <button
      type="button"
      onClick={() => setFavorite((value) => !value)}
    >
      {favorite ? 'お気に入り済み' : 'お気に入り'}
    </button>
  )
}

Client Componentが必要になる代表例は次のとおりです。

  • useState
  • useEffect
  • onClick
  • onChange
  • localStorage
  • WebSocketのブラウザ接続
  • Canvas
  • Geolocation API
  • モーダルやタブのローカル状態

基本方針は次のようになります。

まずServer Componentとして作る
  ↓
ブラウザ状態やイベントが必要な部分だけClient Componentにする

ページ全体を安易にClient Componentにすると、ブラウザへ送るJavaScriptが増え、Server Componentの利点を失いやすくなります。

6. Next.jsにおけるデータの読み取り

Next.js App Routerでは、Server Componentからデータソースを直接呼び出せます。

import { listReservations } from '@/features/reservations/query'

export default async function ReservationsPage() {
  const reservations = await listReservations()

  return (
    <ul>
      {reservations.map((reservation) => (
        <li key={reservation.id}>
          {reservation.customerName}
        </li>
      ))}
    </ul>
  )
}

listReservations()の中では、DBや外部APIを呼び出せます。

export async function listReservations() {
  return db.reservation.findMany({
    orderBy: {
      startAt: 'asc',
    },
  })
}

同じNext.jsアプリケーション内であれば、Server Componentから自分自身のAPIを呼び出す必要はありません。

避けたい構成は次のとおりです。

Server Component
  → 自分のRoute HandlerへHTTP通信
  → Service
  → DB

基本構成は次のとおりです。

Server Component
  → Service / Query
  → DB

ブラウザ側から動的に取得する必要がある場合は、Route Handlerや外部APIを利用します。

7. Next.jsにおけるデータの更新

画面からサーバー状態を更新する方法として、Server Actionsを利用できます。

// app/reservations/actions.ts
'use server'

import { revalidatePath } from 'next/cache'
import { requireSession } from '@/lib/auth'
import { createReservation } from '@/features/reservations/service'

type ReservationState = {
  success: boolean
  message: string
}

export async function createReservationAction(
  _previousState: ReservationState,
  formData: FormData,
): Promise<ReservationState> {
  const session = await requireSession()

  const customerName = formData.get('customerName')

  if (
    typeof customerName !== 'string' ||
    customerName.trim() === ''
  ) {
    return {
      success: false,
      message: '氏名を入力してください',
    }
  }

  await createReservation({
    userId: session.userId,
    customerName: customerName.trim(),
  })

  revalidatePath('/reservations')

  return {
    success: true,
    message: '登録しました',
  }
}

フォームから呼び出します。

'use client'

import { useActionState } from 'react'
import { createReservationAction } from './actions'

const initialState = {
  success: false,
  message: '',
}

export function ReservationForm() {
  const [state, formAction, pending] = useActionState(
    createReservationAction,
    initialState,
  )

  return (
    <form action={formAction}>
      <input name="customerName" />
      <button type="submit" disabled={pending}>
        {pending ? '登録中...' : '登録'}
      </button>
      {state.message && <p aria-live="polite">{state.message}</p>}
    </form>
  )
}

<form action> に渡す関数は戻り値を返さない前提の型なので、結果メッセージを返す Action はそのままでは渡せません。
useActionState を挟むと、Action の第1引数が前回の状態、第2引数が FormData になり、戻り値を画面へ出せます。
Server Actionsは、Next.jsの画面専用の登録・更新・削除処理と相性がよい機能です。

一方、外部クライアントへHTTP APIを提供する場合はRoute Handlerを使います。

8. Route HandlerによるHTTP API

App Routerでは、route.tsにHTTPハンドラーを定義します。

// app/api/products/route.ts
import { NextResponse } from 'next/server'
import { listProducts } from '@/features/products/query'

export async function GET() {
  const products = await listProducts()

  return NextResponse.json({
    products,
  })
}

POSTも定義できます。

export async function POST(request: Request) {
  const body: unknown = await request.json()

  // 入力検証・認証・認可
  // Serviceの呼び出し

  return NextResponse.json(
    {
      success: true,
    },
    {
      status: 201,
    },
  )
}

Route Handlerが適している用途は次のとおりです。

  • モバイルアプリ向けAPI
  • 外部サービス向けAPI
  • Webhook
  • OAuthコールバック
  • IoTデバイスからの通信
  • ファイルダウンロード
  • SSEやストリーミング
  • CORS制御が必要なAPI

Server ActionsとRoute Handlersは競合する仕組みではありません。

Next.js画面専用の更新
  → Server Action

HTTPインターフェース
  → Route Handler

共通業務ロジック
  → Service / Use Case

9. ページ遷移はMPAとSPAの長所を組み合わせる

通常のMPAでは、リンクをクリックするたびに新しいHTMLページを読み込みます。

リンクをクリック
  ↓
サーバーへページ全体を要求
  ↓
新しいHTMLを受信
  ↓
ページ全体を置き換え

一般的なSPAでは、最初にJavaScriptアプリケーションを読み込み、その後はブラウザ側で画面を切り替えます。

Next.jsのApp Routerでは、<Link>を使うことで、サーバーで生成されるUIとクライアント側遷移を組み合わせます。

import Link from 'next/link'

export function Navigation() {
  return (
    <nav>
      <Link href="/">ホーム</Link>
      <Link href="/products">商品</Link>
    </nav>
  )
}

Next.jsは、状況に応じて次を行います。

  • リンク先のプリフェッチ
  • クライアント側ナビゲーション
  • 共有レイアウトの保持
  • 必要なRSC Payloadの取得
  • ストリーミング
  • Client Componentの状態保持

そのため、サーバー主導でデータを取得しながら、ページ全体の再読み込みを避けたアプリケーション体験を作れます。

10. loading.tsxとStreaming

データ取得に時間がかかる場合、ページ全体の完了を待つのではなく、準備できた部分から表示できます。

app/
└── dashboard/
    ├── page.tsx
    └── loading.tsx
// app/dashboard/loading.tsx
export default function Loading() {
  return <p>読み込み中...</p>
}

loading.tsxはSuspense境界を作り、ページ本体の準備中にフォールバックUIを表示します。

より細かく制御したい場合は、コンポーネント単位でSuspenseを使います。

import { Suspense } from 'react'
import { SalesSummary } from './SalesSummary'
import { LatestOrders } from './LatestOrders'

export default function DashboardPage() {
  return (
    <main>
      <h1>Dashboard</h1>

      <Suspense fallback={<p>売上を読み込み中...</p>}>
        <SalesSummary />
      </Suspense>

      <Suspense fallback={<p>注文を読み込み中...</p>}>
        <LatestOrders />
      </Suspense>
    </main>
  )
}

この仕組みにより、遅い処理がページ全体の表示を止めることを避けられます。

11. キャッシュと再検証

Next.jsでは、データやレンダリング結果をキャッシュして再利用できます。

ただし、キャッシュは単なる高速化設定ではありません。

どのデータを
いつまで再利用し
何をきっかけに最新化するか

というアプリケーション設計の一部です。

データ更新後は、対象のパスやデータを再検証します。

import { revalidatePath } from 'next/cache'

revalidatePath('/products')

キャッシュ戦略は、データの性質で変わります。

会社概要
  → 長期間キャッシュ可能

商品マスタ
  → 更新時に再検証

予約の空き状況
  → 短時間または動的取得

ユーザー固有情報
  → 共有キャッシュに載せない

ここで前提を1つ補足します。
Next.js 16 のキャッシュには、next.config.tscacheComponents: true を有効にする Cache Components と、それを使わない従来モデルの2つがあります。

Cache Components 有効
  'use cache' と <Suspense> で、静的シェル・キャッシュ済み・リクエスト時生成を
  同じルート内に混在させる

無効(従来モデル)
  ルート単位の静的・動的判定と、fetch の個別キャッシュ指定を使う
  fetch は既定ではキャッシュされない

本記事は従来モデルを前提に書いています。
コンポーネント単位のキャッシュを前提にした記事やサンプルを読むときは、cacheComponents が有効かどうかを先に確認します。
キャッシュ関連のAPIと推奨モデルはバージョンで変わるため、最終的には利用中のバージョンの公式ドキュメントで確認します。

12. 画像・フォント・メタデータの最適化

Image

Next.jsのImageコンポーネントは、画像サイズ、遅延読み込み、レイアウトシフト対策などを支援します。

import Image from 'next/image'

export function HeroImage() {
  return (
    <Image
      src="/hero.jpg"
      alt="サービス紹介"
      width={1200}
      height={630}
      preload
    />
  )
}

Next.js 16 で priority は非推奨になり、意図が分かりやすい preload に置き換わりました。
すべてのヒーロー画像へ機械的に付けるのではなく、LCP の対象と判断できる画像だけに限定します。

Font

next/fontを使うと、フォントをアプリケーションの静的アセットとして扱い、外部フォント取得による表示遅延を抑えられます。

import { Noto_Sans_JP } from 'next/font/google'

const notoSansJp = Noto_Sans_JP({
  subsets: ['latin'],
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="ja">
      <body className={notoSansJp.className}>
        {children}
      </body>
    </html>
  )
}

Metadata

Metadata APIで、タイトル、説明、OG情報などを定義できます。

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: '商品一覧',
  description: '商品の一覧ページです',
  openGraph: {
    title: '商品一覧',
    description: '商品の一覧ページです',
  },
}

動的ページではgenerateMetadata()を利用できます。

export async function generateMetadata({
  params,
}: {
  params: Promise<{ id: string }>
}): Promise<Metadata> {
  const { id } = await params
  const product = await getProduct(id)

  return {
    title: product.name,
    description: product.description,
  }
}

Next.jsを使うだけで自動的にSEOが完成するわけではありません。

ページの内容、メタデータ、構造化データ、URL設計、表示速度を適切に設計する必要があります。

13. Next.jsとReact + Viteの違い

Viteは高速な開発サーバーとビルド環境を提供します。

React + Viteでは、一般的にブラウザ中心のSPAを作ります。

React + Vite
  Reactアプリケーションをブラウザで実行する構成を作りやすい

Next.js
  Reactをブラウザとサーバーの両方で利用する構成を標準化する

比較すると次のようになります。

観点 Next.js React + Vite
位置づけ Reactフルスタックフレームワーク 開発サーバー・ビルドツール
ルーティング App Routerを標準搭載 React Routerなどを追加
Server Components 統合されている 通常は利用しない
SSR・静的生成 標準機能 別の構成が必要
サーバー処理 Server Actions、Route Handlers 通常は別バックエンド
画像・フォント 専用最適化機能 自分で構成
デプロイ Node、Docker、Vercel、静的出力など 静的配信が容易
学習コスト 高め 比較的低い
設計自由度 標準構成が強い 自由度が高い

Next.jsが向いているケース

  • 公開WebサイトとWebアプリを一体で作る
  • SEOや初期表示が重要
  • サーバーから直接データを取得したい
  • 認証付き業務アプリを作る
  • フロントエンドとBFFを一つのリポジトリで管理する
  • Server Componentsを利用したい
  • ページごとに静的・動的レンダリングを使い分けたい

React + Viteが向いているケース

  • ブラウザ内で完結するSPA
  • バックエンドAPIがすでに存在する
  • 社内管理画面でSEOが不要
  • 静的ホスティングだけで運用したい
  • React以外のサーバー構成を独立して管理したい
  • Next.js固有の実行モデルが不要

「Next.jsの方が高機能だから常に優れている」ということではありません。

必要な実行モデルで選択します。

14. Next.jsはバックエンドを完全に置き換えるのか

Next.jsにはサーバー機能がありますが、すべてのバックエンドをNext.jsへ集約すべきとは限りません。

Next.jsのサーバー機能が向いているものは次のとおりです。

  • Web画面用のBFF
  • フォーム処理
  • 認証付きCRUD
  • コンテンツ取得
  • 小規模から中規模の業務処理
  • Webhook
  • 外部APIの集約
  • Server Actions
  • Route Handlers

独立バックエンドを検討するものは次のとおりです。

  • 複数クライアントで共有する大規模API
  • 高負荷な非同期処理
  • 長時間バッチ
  • 複雑なイベント駆動処理
  • 多数のマイクロサービス
  • 独立したスケーリングが必要な処理
  • WebSocketや常時接続を中心とした基盤
  • 厳格なAPIライフサイクル管理

典型的な構成は次のいずれかです。

Next.jsをどこまで使うかの3パターン。A(Next.jsのみ)はBrowser→Next.js→Databaseで小〜中規模を1つで完結。B(BFFとして使う)はBrowser→Next.js→Backend API→Databaseで既存API資産を活かす。C(フロントとして使う)はBrowser→Next.js→既存のAPI基盤で、バックエンドは独立運用する

テキスト版を開く
A. Next.js のみ          B. BFF として使う        C. フロントとして使う
Browser                  Browser                  Browser
  ↓                        ↓                        ↓
Next.js                  Next.js                  Next.js
  RSC / Server Actions     画面向けの集約層          表示とルーティング
  Route Handlers           認証・整形                更新は API へ
  ↓                        ↓                        ↓
Database                 Backend API              既存の API 基盤
                           ↓
                         Database

Next.jsはフルスタック開発ができますが、必ずモノリスにする必要はありません。

15. 最小構成で開始する

新しいNext.jsプロジェクトはcreate-next-appで作成できます。

npx create-next-app@latest my-app
cd my-app
npm run dev

ブラウザで次を開きます。

http://localhost:3000

TypeScriptとApp Routerは、特別な理由がなければ有効にして開始するのが一般的です。

作成後の代表的な構成は次のようになります。

my-app/
├── app/
│   ├── favicon.ico
│   ├── globals.css
│   ├── layout.tsx
│   └── page.tsx
├── public/
├── next.config.ts
├── package.json
├── tsconfig.json
└── eslint.config.mjs

代表的なコマンドは次のとおりです。

npm run dev
npm run build
npm run start
npm run dev
  → 開発サーバー

npm run build
  → 本番ビルド

npm run start
  → 本番用Node.jsサーバー

Node.jsの最低バージョンなどはNext.jsのバージョンごとに変わるため、導入時に公式のInstallationページを確認します。

16. ディレクトリ構成の考え方

小規模なアプリでは、app配下にコンポーネントやActionをまとめても問題ありません。

app/
└── reservations/
    ├── page.tsx
    ├── ReservationForm.tsx
    └── actions.ts

規模が大きくなる場合は、ルーティングと業務ロジックを分けます。

app/
├── reservations/
│   ├── page.tsx
│   ├── ReservationForm.tsx
│   └── actions.ts
└── api/
    └── reservations/
        └── route.ts

features/
└── reservations/
    ├── query.ts
    ├── command.ts
    ├── schema.ts
    └── types.ts

lib/
├── auth.ts
├── db.ts
└── logger.ts

役割は次のようになります。

app/
  ルーティングとUI境界

features/
  ユースケース・業務ロジック

lib/
  DB、認証、ログなどの共通基盤

Next.jsがフォルダ構成をすべて決めてくれるわけではありません。

ルーティング以外のコードは、プロジェクト規模に応じて整理する必要があります。

17. デプロイ方法

Next.jsはVercel以外にもデプロイできます。

Vercel

Next.jsとの統合が強く、Gitリポジトリを接続してデプロイできます。

Gitへpush
  ↓
自動ビルド
  ↓
Preview環境
  ↓
本番デプロイ

Node.jsサーバー

Node.jsを実行できる環境なら、一般的なサーバーとして起動できます。

npm run build
npm run start

VPS、クラウドVM、PaaSなどで利用できます。

Docker

Next.jsアプリケーションをコンテナ化して実行できます。

Docker
  → Kubernetes
  → Azure Container Apps
  → Amazon ECS
  → Google Cloud Run
  → 任意のコンテナ基盤

Static Export

サーバー機能を必要としないページは、静的ファイルとして書き出せます。

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  output: 'export',
}

export default nextConfig

Static Export には実行時の Next.js サーバーがありません。
Server Component 自体はビルド時に実行されるので使えますが、リクエスト時のサーバー処理を伴う機能は利用できません。

区分 内容
使える Server Component(ビルド時に実行)/ Client Component / export const dynamic = 'force-static' を付けた GET Route Handler / カスタムローダーを設定した next/image
使えない Server Actions / cookies()Request に依存する Route Handler / ISR / Proxy / rewrites・redirects・headers / Draft Mode / Intercepting Routes / generateStaticParams() の無い動的ルート / dynamicParams: true / 既定ローダーによる画像最適化

「Route Handler が丸ごと使えない」と誤解しやすいところですが、ビルド時に応答を確定できる GET は静的ファイルとして書き出せます。
使えないのは、受信リクエストの値を参照するものと POST などです。

したがって、Vercel以外へ出す場合に必ずoutput: 'export'を使うわけではありません。

Node.jsを実行できる
  → 通常のNext.jsサーバーとしてデプロイ可能

コンテナを実行できる
  → Dockerでデプロイ可能

静的ファイルしか配置できない
  → Static Exportを検討

18. Next.jsを採用するときの注意点

1. サーバーとブラウザの境界を理解する必要がある

同じReactコンポーネントに見えても、実行場所が異なります。

Server Component
Client Component
Server Action
Route Handler

これらの境界を意識しないと、秘密情報の漏えい、不要なJavaScript配信、Hydrationエラーにつながります。

2. キャッシュを理解する必要がある

データが更新されない、開発環境と本番環境で挙動が違う、といった問題はキャッシュ設計から発生しやすくなります。

3. Next.js固有の知識が増える

Reactに加えて、次を学ぶ必要があります。

  • App Router
  • Server Components
  • Client Components
  • Server Actions
  • Route Handlers
  • Streaming
  • Metadata
  • キャッシュと再検証
  • デプロイ時のRuntime

4. バージョン更新の影響を受ける

Next.jsは継続的に機能が追加・変更されます。

古い記事のコードが現行バージョンの推奨方法と一致しない場合があります。

記事やサンプルを見るときは、次を確認します。

Next.jsのバージョン
App RouterかPages Routerか
Reactのバージョン
キャッシュモデル
デプロイ先

5. セキュリティは自動ではない

Next.jsを使っても、次は自分で実装します。

  • 認証
  • 認可
  • 入力検証
  • テナント分離
  • CSRF・CORS設計
  • レート制限
  • 監査ログ
  • 秘密情報管理
  • 依存パッケージ更新

Server ActionやRoute Handlerは、外部入力を受け取るネットワーク境界として扱います。

19. よくある誤解

「Next.jsを使えばSEO対策は完了する」

誤りです。

Next.jsはHTML生成やMetadata APIを提供しますが、コンテンツ品質、構造、URL、内部リンク、表示速度などは別途設計します。

「Client Componentはサーバーでは実行されない」

不正確です。

初回表示では、Client ComponentもHTML生成のためサーバー側で事前レンダリングされる場合があります。
その後、ブラウザでHydrationされます。

「Server Componentなら常にSSRになる」

誤りです。

Server Componentはサーバーで実行されるコンポーネントモデルです。
静的に事前生成される場合も、リクエスト時に動的生成される場合もあります。

「Server Actionsを使えばAPIは不要になる」

誤りです。

外部クライアント、Webhook、ファイル配信、HTTPステータス制御などにはRoute Handlerが必要です。

「Next.jsはVercelでしか動かない」

誤りです。

Node.jsサーバー、Docker、静的書き出し、プラットフォームアダプターなど複数のデプロイ方法があります。
ただし互換性は同列ではありません。
Node.js サーバーと Docker は全機能を使えますが、Static Export は上記のとおり機能が限定され、アダプターは実装ごとに対応範囲が違います。

「Next.jsはフロントエンドだけの技術」

現在のNext.jsは、UIだけでなくサーバー処理も持つフルスタックフレームワークです。

ただし、大規模バックエンドを必ずNext.js内に実装するという意味ではありません。

20. Next.jsを理解するための全体モデル

Next.js App Routerの処理を一つの図にすると、次のようになります。

Browser・Next.js・Database の3層図。Browser には Client Components と State / Event / DOM API があり、Navigation / Action / API リクエストで Next.js へつながる。Next.js には App Router、Server Components、Server Actions、Route Handlers、Cache / Revalidation、Metadata / Optimization が並び、Service / Use Case を介して Database / External API へつながる。読み取りと更新は同じ層を通る

テキスト版を開く
Browser
  Client Components
  State / Event / DOM API
    ↓ Navigation / Action / API リクエスト
Next.js
  App Router
  Server Components
  Server Actions
  Route Handlers
  Cache / Revalidation
  Metadata / Optimization
    ↓ Service / Use Case
Database / External API / File / Queue

役割分担を短くまとめると次のとおりです。

関心事とNext.jsの仕組みの対応表。画面構造はReact Component、URLはApp Router、表示データの取得はServer Component、ブラウザ状態・イベントはClient Component、画面専用のデータ更新はServer Action、HTTPインターフェースはRoute Handler、業務ロジックはService / Use Case、DBアクセスはRepository / DB Client、最新化はCache / Revalidationが担当する

テキスト版を開く
画面構造              → React Component
URL                   → App Router
表示データの取得      → Server Component
ブラウザ状態・イベント → Client Component
画面専用のデータ更新  → Server Action
HTTPインターフェース  → Route Handler
業務ロジック          → Service / Use Case
DBアクセス            → Repository / DB Client
最新化                → Cache / Revalidation

21. まとめ

Next.jsは、Reactに便利な機能を少し追加しただけのツールではありません。

Reactコンポーネントを中心に、次の領域を一体化するフレームワークです。

ルーティング
レンダリング
サーバー処理
データ取得
データ更新
キャッシュ
最適化
エラー処理
デプロイ

Reactとの関係は次のように整理できます。

React
  UIをコンポーネントとして表現する

Next.js
  そのコンポーネントを
  どのURLで
  どこで実行し
  どうデータを取得し
  どう更新し
  どう配信するかを構成する

最終的には、次の一文に収まります。

Next.jsは、Reactを使って、サーバーとブラウザの両方にまたがるWebアプリケーションを構築・最適化・配信するためのフルスタックフレームワークです。

冒頭に書いたとおり、ここまで目新しい話は1つもありません。
それでも書き出してみて分かったのは、「知っている」と思っていた範囲が、機能単位ではつながっていても地図としてはつながっていなかったことでした。

次に迷ったときは、20章の全体モデルの図に戻れば足りるはずです。

本シリーズの関連記事

本記事はNext.jsの全体像を扱いました。
個別の論点は次の記事で掘り下げています。

  • Next.jsのServer ActionsをRSC・React 19から理解する
  • Next.js App RouterでServer Actions方式とAPI方式をどう使い分けるか

参考資料

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?