Next.js AppディレクトリでAPIルートが404エラーになる
ポイント
この問題はNext.js 13以降のApp Routerを導入したプロジェクトで頻発します。原因は主にファイル命名規則の変更と関数定義方法の変化にあります。
発生する問題状況
Next.js 13で導入されたApp Router(app
ディレクトリ)を使用する場合、APIエンドポイントへアクセスすると404 Not Foundエラーが発生します。具体的な症状として:
- APIルート(
app/api/**
)へのGET/POSTリクエストが404を返す - Postman, curl, クライアントアプリからアクセスしても同様のエラー
app/api/admin/all.js
のような実装では機能しない
例示されたAPIコード(実際は動作しない):
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default async function all(req, res) {
if (req.method !== 'GET') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const admins = await prisma.admin.findMany();
return res.status(200).json(admins);
} catch (error) {
return res.status(500).json({ error: 'Failed to get admins' });
}
}
このエラーが発生する主要原因は以下の2点です:
- ファイル名が新しい命名規則に沿っていない
- 関数の定義方法がPages Routerの方法で実装されている
正しいAPI実装方法
解決策 1: 基本のAPIルート設定
重要
Next.js App Routerでは、APIエンドポイントファイルの名前は**route.js
またはroute.ts
** でなければなりません(Next.js 13.4以降)。
正しいファイル構造
app/
└── api/
└── admin/
└── route.js # ファイル名がキーポイント
正しいコード実装
import { NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
// Prismaクライアントの効率的な初期化
const prisma = new PrismaClient();
export async function GET(request) {
// メソッドチェックは不要(GET関数なので)
try {
const admins = await prisma.admin.findMany();
return NextResponse.json(admins);
} catch (error) {
return NextResponse.json(
{ error: "Failed to get admins" },
{ status: 500 }
);
}
}
export async function POST(request) {
try {
// リクエストボディの取得
const body = await request.json();
// データ処理...
const newAdmin = await prisma.admin.create({ data: body });
return NextResponse.json(newAdmin, { status: 201 });
} catch (error) {
return NextResponse.json(
{ error: "Failed to create admin" },
{ status: 500 }
);
}
}
主な変更点
all.js
→route.js
へのファイル名変更export default async function
→export async function GET/POST
へ変更res.json()
→NextResponse.json()
へ変更- メソッドごとに関数を分離(GET用、POST用など)
アクセスURLも/api/admin/all
ではなく/api/admin
になります。
解決策 2: リクエストボディの取得方法
APIルートでPOSTデータを扱う場合、以下の方法でリクエストボディを取得します:
export async function POST(request) {
// リクエストボディをJSONとして取得
const data = await request.json();
// データ処理...
}
本番環境での追加注意点
重要設定
Next.js 14以降で本番ビルド時にAPIが動作しない場合、next.config.js
の設定を確認してください。output: "export"
が含まれているとAPIルートが無効になります。
/** @type {import('next').NextConfig} */
module.exports = {
// 以下の設定があるとAPIが機能しない
// output: 'export', // コメントアウトまたは削除
// 推奨設定例
eslint: {
ignoreDuringBuilds: true,
},
images: {
unoptimized: true, // 静的エクスポート時のみ必要
},
};
この設定があると、VercelやAWS Amplifyへのデプロイ時に次のエラーが発生します:
- 開発環境ではAPIが動作する
- 本番ビルド後404エラーが発生する
最適化とベストプラクティス
import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; // グローバルインスタンスの例
// 最適化: 環境変数を使用したAPI保護
const API_SECRET = process.env.API_SECRET;
export async function GET(request) {
// 認証ヘッダーチェック
const authHeader = request.headers.get('authorization');
if (authHeader !== `Bearer ${API_SECRET}`) {
return NextResponse.json(
{ error: "Unauthorized" },
{ status: 401 }
);
}
try {
// ページネーション実装例
const { searchParams } = new URL(request.url);
const page = parseInt(searchParams.get('page') || '1');
const limit = 10;
const admins = await prisma.admin.findMany({
take: limit,
skip: (page - 1) * limit,
});
return NextResponse.json(admins);
} catch (error) {
console.error("[API Error]", error);
return NextResponse.json(
{ error: "Internal Server Error" },
{ status: 500 }
);
}
}
ベストプラクティス
Prismaクライアント管理
new PrismaClient()
を毎回実行せず、グローバルインスタンスを使用しますjavascriptimport { PrismaClient } from '@prisma/client'; const globalForPrisma = globalThis; const prisma = globalForPrisma.prisma || new PrismaClient(); if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma; export default prisma;
環境変数による保護
公開APIには必ず認証を実装エラーログの記録
console.error
で開発時にエラー内容を確認可能に安全なヘッダー設定
return NextResponse.json(data, { headers: { 'Content-Type': 'application/json' } });
まとめ:実装ステップ
- APIファイル名を
route.js|ts
に変更 - HTTPメソッドごとに関数を分離(GET, POSTなど)
request
パラメータとNextResponse
を使用- 本番環境用に
next.config.js
を確認 - 必要なら環境変数による認証を実装
- Prismaクライアントはグローバルインスタンス化
これらの手順により、app
ディレクトリ内で正しくAPIルートが機能するようになります。特にファイル命名と関数定義の変更がポイントで、これらを適用するだけで多くの404問題は解決します。