Next.jsのApp RouterにおけるAPIルート設定
Next.jsのApp Router(appディレクトリ)では、APIルートの設定方法がpagesディレクトリとは異なります。2023年2月以降のバージョン(特に13.2以降)で導入されたRoute Handlersを使用することで、モダンなAPIエンドポイントを実装できます。
問題点:App Routerへの移行時のエラー
伝統的なpages/api
ディレクトリにあるAPIルート(例: pages/api/accounts/login.js
)をApp Router(app
ディレクトリ)に移動しようとすると、以下のエラーが発生します:
Server Error
Error: Cannot find module for page: /api/accounts/login
この原因は:
- App Routerが
page.js
の代わりにroute.js
/route.ts
を使用する - ファイル配置パスが異なる(
app/api/[エンドポイント]/route.js
構造が必要) - 関数のエクスポート方法が変更されている
解決策:Route Handlersの使用
App RouterでAPIルートを作成する正しい方法は以下の通りです:
ディレクトリ構造の作成
APIエンドポイントに対応するディレクトリをapp/api
以下に作成し、route.js
またはroute.ts
ファイルを配置します:app/ ├── api/ │ └── accounts/ │ └── login/ │ └── route.js ← 重要
HTTPメソッドごとの関数をエクスポート
route.js
ファイルで、対応するHTTPメソッド名の関数をエクスポート:javascript// app/api/accounts/login/route.js import { NextResponse } from 'next/server'; // GETリクエストのハンドリング export async function GET(request) { console.log(await request.json()); return NextResponse.json({ status: 'success' }, { status: 200 }); } // POSTリクエストのハンドリング export async function POST(request) { const data = await request.json(); // ログイン処理など... return NextResponse.json({ message: 'Logged in' }, { status: 201 }); }
エンドポイントへのアクセス
上記の例では以下のURLでアクセス可能:http://localhost:3000/api/accounts/login
重要な注意点
WARNING
- ファイル名は必ず**
route.js
**(TypeScriptならroute.ts
)にしてください。page.js
やhandler.js
などでは機能しません request
オブジェクトはWeb標準のRequest APIを実装- レスポンス生成には
NextResponse
を使用します
コードの完全例 (TypeScript版)
// app/api/example/route.ts
import { NextResponse } from 'next/server';
type ResponseData = {
message: string;
timestamp: number;
};
export async function GET(req: Request) {
// クエリパラメータ取得例
const url = new URL(req.url);
const name = url.searchParams.get('name') || 'Guest';
return NextResponse.json<ResponseData>({
message: `Hello, ${name}!`,
timestamp: Date.now()
}, {
status: 200,
headers: { 'Cache-Control': 'public, max-age=60' }
});
}
export async function POST(req: Request) {
// リクエストボディ取得例
const body = await req.json();
if(!body.email) {
return NextResponse.json(
{ error: 'Email is required' },
{ status: 400 }
);
}
// DB操作など...
return NextResponse.json({
success: true,
data: { ...body, id: Date.now() }
});
}
従来方式との主な違い
特徴 | Pages Router (pages/api ) | App Router (app/api ) |
---|---|---|
ファイル名 | [endpoint].js | route.js |
HTTPメソッド | req.method で分岐 | 各メソッドごとに個別関数 (GET , POST など) |
レスポンス生成 | Node.js形式 (res.status(200).json() ) | NextResponse.json() |
静的エクスポート | 可能 | 現時点で不可 |
エッジ環境 | 設定可能 | デフォルトでエッジ互換 |
トラブルシューティング
- 404エラーが発生する場合:
- ファイル名が
route.js
になっているか確認 - ディレクトリ構造が
app/api/[endpoint]/route.js
になっているか確認 - 再ビルドを実行:
npm run build
→npm start
- ファイル名が
段階的な移行のすすめ
既存プロジェクトを移行する場合:
app
とpages
ディレクトリを併存可能- 特定エンドポイントから順次移行
next.config.js
で両形式をサポート:jsmodule.exports = { experimental: { appDir: true, // App Router有効 }, }
ベストプラクティス
関数の分割
ビジネスロジックは別ファイルに切り出し:js// utils/auth.js export async function authenticate(credentials) { /* 認証ロジック */ } // app/api/login/route.js import { NextResponse } from 'next/server'; import { authenticate } from '@/utils/auth'; export async function POST(request) { const credentials = await request.json(); const user = await authenticate(credentials); return NextResponse.json(user); }
エラーハンドリング
共通エラーハンドラを使用:jsexport async function GET(request) { try { throw new Error('Test error'); } catch (error) { return NextResponse.json( { error: error.message }, { status: 500 } ); } }
APIルートの推奨フロー
App RouterのAPIルートは、モダンなWeb標準に準拠しつつ、Next.jsの最新機能を活用できます。バージョンアップに伴う仕様変更があるため、公式ドキュメントで常に最新情報を確認してください。