はじめに|この記事で得られる価値
「Next.js App RouterでAPI連携、どの方法がベスト?」
そんな悩み、現場のエンジニアなら一度は通る道です。
Server Components・SWR/React Query・Server Actions…選択肢が増え「これで良いのか?」と迷った経験はありませんか?
特に「fetchはサーバーで?クライアントで?」「Route Handlersはもう不要?」「新機能のCORSやキャッシュ、どう設計すれば?」――後輩レビューや技術選定を任されるほど「自信を持って方針を示せる根拠」が欲しくなりますよね。
本記事は、そんな“現場のモヤモヤ”に寄り添いながら、App Router時代のAPI連携パターン4選を徹底比較&FAQ付きで整理します。
・Next.js(App Router)でAPI実装に迷っている
・エラーや設計の“落とし穴”を現場目線で理解したい
・コピペOKの実践コード・FAQまで欲しい
という方におすすめです。
(Next.jsの基礎やAPI設計の全体像については『フロントエンドフレームワーク徹底比較!React・Vue・Angular違いと選び方』もご参照ください)
用語解説:Next.js
ReactベースのWebアプリケーションを高速・柔軟に構築できるフレームワーク。SSRやAPI連携、ルーティング機能が充実。用語解説:App Router
Next.jsの新しいルーティング方式。ページ・API・UIの構成を柔軟に管理でき、Server ComponentsやServer Actionsなど最新機能と連携。用語解説:API連携
外部サービスや自社サーバーとデータをやり取りする仕組み。fetchやAxiosなどのHTTPクライアントを使う。用語解説:Server Components
サーバー側でレンダリングされるReactコンポーネント。初期表示が高速で、クライアントJSの負荷を軽減。用語解説:SWR/React Query
Reactで非同期データ取得・キャッシュ・ローディング管理を簡単に実装できるライブラリ。用語解説:Server Actions
Next.jsの新機能。サーバー上の関数を直接呼び出し、フォーム送信やデータ更新を型安全に実装できる。用語解説:Route Handlers
Next.jsでAPIエンドポイントを定義する仕組み。外部サービス連携やWebhook受信などに利用。用語解説:fetch
JavaScript標準のHTTPリクエストAPI。サーバー・クライアント両方で利用可能。用語解説:CORS
異なるドメイン間でリソースをやり取りする際のセキュリティ制約。API連携時にエラー原因となることが多い。用語解説:キャッシュ
取得したデータを一時保存し、再取得を高速化する仕組み。fetchやSWR/React Queryで制御可能。
1. 最適なAPI連携は?【フローチャートで一発診断】
本題の前に結論サマリから。
下記フローチャートで、要件に合うAPI連携パターンを瞬時に絞り込めます。
[スタート]
↓
[Q1: 主な目的はデータの「取得」か「更新」か?]
├── [取得] → [Q2: ユーザー操作に応じた頻繁な再取得が必要か?]
│ ├── [はい] → (A) Client Components (SWR/React Query)
│ └── [いいえ] → (B) Server Components (fetch)
└── [更新] → [Q3: 外部サービス用の公開APIエンドポイントが必要か?]
├── [はい] → (C) Route Handlers
└── [いいえ] → (D) Server Actions
- (A) Client Components…リアルタイム性重視のダッシュボードUIに
- (B) Server Components…ブログ等、静的な初回表示に
- (C) Route Handlers…Webhookや外部API用の明示的なエンドポイントに
- (D) Server Actions…フォーム送信など、内部完結のデータ更新に
なぜこの診断になるのか?次章から「現場目線の理由」と「実践コード」で深掘りします。
2. どう変わった?App RouterのAPI設計【RSCとServer Actionsの役割】
■ React Server Components(RSC)とは?
サーバーで直接fetchし、HTMLだけをクライアントへ返せます。
バンドルサイズ削減・初期表示の高速化も容易に。
(Reactのサーバー・クライアントの違いについては『ReactのuseStateとuseEffectの違いとは?初心者が実務で迷わない使い分け完全ガイド』もご参照ください)
用語解説:React Server Components(RSC)
サーバーでレンダリングされるReactコンポーネント。クライアント側のJS負荷を減らし、SEOやパフォーマンス向上に貢献。用語解説:バンドルサイズ
Webアプリの配信時にまとめられるJSやCSSなどのファイル容量。小さいほど表示が速くなる。
■ Server Actionsのインパクト
サーバー上の関数を「直接」呼び出せるRPC的な設計。
フォーム送信等の「更新」処理を、API Route不要&型安全に実装できます。
(型安全なフォーム設計・バリデーションについては『TypeScriptフォームバリデーション徹底比較|Zod・Yup・React Hook Formの違いと選び方』もご参照ください)
用語解説:型安全
プログラムの型(string, numberなど)が正しく扱われることで、バグやエラーを未然に防ぐ設計。用語解説:RPC
Remote Procedure Callの略。ネットワーク越しにサーバー上の関数を直接呼び出す仕組み。
この2つの登場で、Pages Router時代のAPI連携の常識が一変しました。
3. 主要4パターンを比較!【現場ユースケースで解説】
■ 3.1 Client Components(SWR/React Query):動的UI向け
- こんなとき最適: チャットや通知、リアルタイム管理画面など即時反応UI
- メリット: useSWR等のHooksで宣言的にデータ取得。キャッシュやローディング管理も自動
- デメリット: バンドルサイズ増加(クライアントJS依存)/ライブラリ依存性
- アンチパターン: 静的な初回表示だけならServer Componentsが高速&省コスト
用語解説:Client Components
クライアント(ブラウザ)側で動作するReactコンポーネント。ユーザー操作に即時反応できる。用語解説:Hooks
Reactの機能拡張API。useStateやuseEffect、useSWRなど、状態管理や副作用処理を簡単に記述できる。
■ 3.2 Server Components(fetch):シンプル&パフォーマンス最適
- こんなとき最適: ブログやニュース記事など“静的な初期データ”の表示
- メリット: async/awaitで自然にデータ取得。超軽量・高速。キャッシュ制御が柔軟(next.revalidate)
- デメリット: ユーザー操作による再取得はページ遷移or再読み込みが必要
- アンチパターン: オートコンプリートなど、即時反応UIには非推奨
用語解説:async/await
JavaScriptの非同期処理を直感的に記述できる構文。API取得やデータ処理で多用される。用語解説:next.revalidate
Next.jsのキャッシュ制御オプション。指定秒数ごとにデータを再取得し、最新状態を保つ。
■ 3.3 Route Handlers(API Routes):明示的なAPIエンドポイントに
- こんなとき最適: Webhook受信や、外部アプリへのAPI提供
- メリット: RESTful設計をNext.jsで実現。Webhookや外部連携の「入り口」にも
- デメリット: 内部処理のみならServer Actionsの方がシンプル&型安全
- アンチパターン: ログインユーザーの単純なデータ更新はServer Actionsへ
用語解説:RESTful設計
Web API設計の標準。リソースごとにURLを分け、HTTPメソッド(GET/POSTなど)で操作する。用語解説:Webhook
外部サービスからの通知やイベントを受け取る仕組み。APIエンドポイントで受信する。
■ 3.4 Server Actions:型安全&モダンなデータ更新
- こんなとき最適: 問い合わせフォームや「いいね」ボタンなど
- メリット: サーバー関数を直接呼べる(API Route不要)。useFormState等でエラー・状態管理も型安全。JS無効環境でも送信可
- デメリット: 設計が新しく最初は学習コストあり。「更新」処理向き
- アンチパターン: 外部アプリ用の汎用APIはRoute Handlersへ
用語解説:useFormState
Next.jsのフォーム状態管理フック。送信結果やエラーを型安全に扱える。用語解説:JS無効環境
JavaScriptが無効なブラウザや端末でもフォーム送信が可能な設計。
4. すぐ試せる!【実践コード3選】
■ 4.1 認証(Auth.js)× Server Components
セッション情報をサーバー側で取得し、表示を切り替える鉄板パターン。
(認証・セッション管理の基礎については『Spring Boot×OAuth2認証の全比較!現場で失敗しない選び方とは?』もご参照ください)
import { auth } from '@/auth';
export default async function HomePage() {
const session = await auth();
return (
<div>
{session?.user ? (
<h1>ようこそ, {session.user.name}さん</h1>
) : (
<h1>ログインしてください</h1>
)}
</div>
);
}
■ 4.2 ヘッドレスCMS(microCMS)× Server Components
fetch+next.revalidateでISRも手軽。
type Props = { params: { id: string } };
async function getPost(id: string) {
const res = await fetch(
`https://YOUR_SERVICE_DOMAIN.microcms.io/api/v1/blog/${id}`,
{
headers: { 'X-MICROCMS-API-KEY': process.env.MICROCMS_API_KEY! },
next: { revalidate: 3600 },
}
);
return res.json();
}
export default async function BlogPostPage({ params }: Props) {
const post = await getPost(params.id);
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
■ 4.3 Server Actions+Zodで型安全フォーム
入力バリデーション〜エラー表示まで「型安全」にまとめられます。
(TypeScriptやZodによる型安全なバリデーションについては『TypeScriptフォームバリデーション徹底比較|Zod・Yup・React Hook Formの違いと選び方』もご参照ください)
// app/actions.ts
'use server';
import { z } from 'zod';
const FormSchema = z.object({
email: z.string().email('有効なメールアドレスを入力してください。'),
});
export async function submitForm(prevState: any, formData: FormData) {
const validatedFields = FormSchema.safeParse({
email: formData.get('email'),
});
if (!validatedFields.success) {
return { errors: validatedFields.error.flatten().fieldErrors };
}
// データベース保存処理など
return { message: '送信成功!' };
}
// app/contact-form.tsx
'use client';
import { useFormState } from 'react-dom';
import { submitForm } from './actions';
const initialState = { message: null, errors: {} };
export function ContactForm() {
const [state, dispatch] = useFormState(submitForm, initialState);
return (
<form action={dispatch}>
<input type="email" name="email" />
{state.errors?.email && <p>{state.errors.email[0]}</p>}
<button type="submit">送信</button>
{state.message && <p>{state.message}</p>}
</form>
);
}
ぜひコードをコピペして、まずは動かしてみてください。
5. よくある疑問・つまずき【FAQで即解決】
-
Q. CORSエラーはなぜ?どこで起きる?
Server ComponentsやRoute Handlers、Server Actionsから外部APIを呼ぶ場合は、サーバー側で実行されるためCORSエラーは発生しません。ハマりやすいのはClient Componentsから外部API直叩きのとき。この場合はRoute
Handlersで「プロキシAPI」を作り、内部経由にするのが定番です。
(CORSエラーの原因と対策については『JavaScriptでCORSエラーが出たときの原因と対処法を徹底解説』もご参照ください) -
Q. Server ActionsがあればRoute Handlersは不要?
No! 両者の棲み分けは明確。
・Server Actions…Next.jsアプリ内部のUI起点のデータ更新
・Route Handlers…Webhook受信や外部サービス向けAPI
現場では“両方使い分け”が基本です。 -
Q. Server Actionsで注意すべきセキュリティは?
CSRFはNext.jsが自動で保護。
ただし「認可(Authorization)」…つまりそのユーザーが操作してよいかの権限チェックは、開発者自身が必ず実装しましょう。 -
Q. キャッシュ戦略のベストプラクティスは?
fetchの第2引数で制御。
・cache: 'no-store'…毎回取得
・next: { revalidate: 秒数 }…ISR
更新後はrevalidatePathやrevalidateTagでオンデマンド破棄も可能。
(APIキャッシュやfetchの使い方については『JavaScriptのAjax完全入門|fetchの使い方・CORSエラーの対処・非同期通信の基本を解説』もご参照ください) -
Q. ClientとServer Components間のデータ受け渡しは?
基本はprops経由で「サーバー→クライアント」へ渡します。逆向き(クライアント→サーバー)はServer ActionsやRoute Handlers経由が安全です。
まとめ|App RouterのAPI設計で“一歩先”へ
App Router時代のAPI連携は、4つの主役を理解するのが最短ルート。
・Server Components(fetch)…静的ページの基本
・Client Components(SWR/React Query)…動的UIで真価発揮
・Route Handlers…Webhookや外部API連携の要
・Server Actions…型安全&モダンなデータ更新
最初は迷って当然。でも、それぞれの得意領域さえ押さえれば、要件ごとに“迷わず選べる”自分になれます。
Next.jsはこれからも進化が続きます。新しい技術をキャッチアップしながら、現場のパフォーマンスも一緒に磨いていきましょう。
ぜひ一度、手元のプロジェクトで実践してみてください!