ClaudeNext.js2025/02/28 14:00

Building APIs with Next.js

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

claudejamodel: claude-sonnet-4-20250514

Next.js App RouterでのAPI構築ガイド

Key Points

  • App RouterのRoute Handlersで標準Web APIを活用
  • 同一ファイルで複数HTTPメソッドをサポート
  • プロキシ層やBFF(Backend for Frontend)として活用可能

Summary

Next.js App RouterのRoute Handlersを使用したAPI構築の包括的なガイドです。従来のPages Routerから移行し、Web標準のRequest/Response APIを活用したモダンなAPI開発手法を解説しています。

Key Points

  • App Router採用: app/ディレクトリ内のroute.tsファイルでAPIエンドポイントを作成
  • Web標準API: Node.js固有のAPIではなく、標準のRequest/Response APIを使用
  • 複数HTTPメソッド対応: 同一ファイル内でGET、POST、PUT、DELETEなどを個別にexport
  • 動的ルーティング: [id]フォルダ構造でパラメータ付きエンドポイントを実装
  • プロキシ機能: 既存バックエンドサービスへの中継層として活用可能
  • 認証ミドルウェア: 再利用可能な認証ロジックをwrapper関数として実装
  • デプロイメント考慮: 標準Node.js、SPA/静的エクスポート、Vercelデプロイの違いを理解
  • Server Components活用: 内部データ取得のみの場合はAPIエンドポイント不要

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

claudejamodel: claude-sonnet-4-20250514

Next.jsでAPIを構築する

このガイドでは、Next.jsでAPIを構築する方法について説明します。プロジェクトのセットアップ、App RouterとRoute Handlersの理解、複数のHTTPメソッドの処理、動的ルーティングの実装、再利用可能なミドルウェアロジックの作成、そして専用のAPIレイヤーをいつ立ち上げるかの判断について説明します。

1. はじめに

1.1 Next.jsアプリの作成

新しく始める場合は、以下のコマンドで新しいNext.jsプロジェクトを作成できます:

npx create-next-app@latest --api

注意: --apiフラグを使用すると、新しいプロジェクトのapp/フォルダにroute.tsの例が自動的に含まれ、APIエンドポイントの作成方法が示されます。

1.2 App Router vs. Pages Router

Pages Router: 従来、Next.jsはAPIにpages/api/*を使用していました。このアプローチはNode.jsのrequest/responseオブジェクトとExpress風のAPIに依存していました。

App Router(デフォルト): Next.js 13で導入されたApp Routerは、Web標準のRequest/Response APIを完全に採用しています。pages/api/*の代わりに、app/ディレクトリ内の任意の場所にroute.tsまたはroute.jsファイルを配置できるようになりました。

なぜ切り替えるのか? App Routerの「Route Handlers」は、Node.js固有のAPIではなく、Web PlatformのRequest/Response APIに依存しています。これにより学習が簡素化され、摩擦が減り、異なるツール間で知識を再利用できるようになります。

2. Next.jsでAPIを構築する理由(とタイミング)

複数のクライアント向けのパブリックAPI

Next.jsウェブアプリ、別のモバイルアプリ、またはサードパーティサービスによって消費されるパブリックAPIを構築できます。例えば、ReactウェブサイトとReact Nativeモバイルアプリの両方で/api/usersからフェッチすることができます。

既存のバックエンドへのプロキシ

外部のマイクロサービスを単一のエンドポイントの背後に隠したり統合したりしたい場合があります。Next.jsのRoute Handlersは、他の既存のバックエンドへのプロキシまたは中間レイヤーとして機能できます。

WebhookとIntegration

外部からのコールバックやwebhook(例:Stripe、GitHub、Twilio)を受信する場合、Route Handlersで処理できます。

カスタム認証

セッション、トークン、その他の認証ロジックが必要な場合、Next.jsのAPIレイヤーでクッキーの保存、ヘッダーの読み取り、適切なデータでの応答ができます。

注意: 自分のNext.jsアプリのためだけにサーバーサイドデータフェッチが必要で(そのデータを外部で共有する必要がない)場合、Server Componentsがレンダリング中に直接データをフェッチするのに十分かもしれません—別のAPIレイヤーは不要です。

3. Route Handlersを使用したAPIの作成

3.1 基本的なファイル設定

App Router(app/)では、ルートを表すフォルダを作成し、その中にroute.tsファイルを配置します。例えば、/api/usersにエンドポイントを作成するには:

app
└── api
    └── users
        └── route.ts

3.2 1つのファイルでの複数のHTTPメソッド

Pages Router APIルート(単一のデフォルトエクスポートを持つ)とは異なり、同じファイルから異なるHTTPメソッドを表す複数の関数をエクスポートできます。

// app/api/users/route.ts
export async function GET(request: Request) {
  // 例:ここでDBからデータをフェッチ
  const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ];
  
  return new Response(JSON.stringify(users), {
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  });
}

export async function POST(request: Request) {
  // リクエストボディを解析
  const body = await request.json();
  const { name } = body;
  
  // 例:新しいユーザーをDBに挿入
  const newUser = { id: Date.now(), name };
  
  return new Response(JSON.stringify(newUser), {
    status: 201,
    headers: { 'Content-Type': 'application/json' }
  });
}

4. Web APIの操作

4.1 RequestとResponseの直接使用

デフォルトでは、Route Handlerメソッド(GETPOSTなど)は標準のRequestオブジェクトを受け取り、標準のResponseオブジェクトを返す必要があります。

4.2 クエリパラメータ

// app/api/search/route.ts
import { NextRequest } from 'next/server';

export function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const query = searchParams.get('query');
  // 例:`/api/search?query=hello`
  
  return new Response(
    JSON.stringify({ result: `You searched for: ${query}` }),
    {
      headers: { 'Content-Type': 'application/json' },
    },
  );
}

4.3 ヘッダーとクッキー

// app/api/auth/route.ts
import { NextRequest } from 'next/server';
import { cookies, headers } from 'next/headers';

export async function GET(request: NextRequest) {
  // 1. 'next/headers'ヘルパーの使用
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
  const headersList = await headers();
  const referer = headersList.get('referer');
  
  // 2. 標準Web APIの使用
  const userAgent = request.headers.get('user-agent');
  
  return new Response(
    JSON.stringify({ token, referer, userAgent }),
    {
      headers: { 'Content-Type': 'application/json' },
    }
  );
}

5. 動的ルート

動的パス(例:/api/users/:id)を作成するには、フォルダ構造でDynamic Segmentsを使用します:

app
└── api
    └── users
        └── [id]
            └── route.ts
// app/api/users/[id]/route.ts
import { NextRequest } from 'next/server';

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  const id = (await params).id;
  
  // 例:ID `id`のユーザーをデータベースで検索
  return new Response(
    JSON.stringify({ id, name: `User ${id}` }),
    {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    }
  );
}

6. Next.jsをプロキシまたは転送レイヤーとして使用

既存のバックエンドサービスをプロキシする一般的なシナリオです。リクエストを認証し、ログを処理し、リモートサーバーやバックエンドに送信する前にデータを変換できます:

// app/api/external/route.ts
import { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const response = await fetch('https://example.com/api/data', {
    // オプション:一部のヘッダーを転送、認証トークンを追加など
    headers: {
      Authorization: `Bearer ${process.env.API_TOKEN}`
    },
  });
  
  // レスポンスを変換または転送
  const data = await response.json();
  const transformed = {
    ...data,
    source: 'proxied-through-nextjs'
  };
  
  return new Response(JSON.stringify(transformed), {
    headers: { 'Content-Type': 'application/json' },
  });
}

7. 共有「ミドルウェア」ロジックの構築

複数のRoute Handlerで同じロジック(認証チェック、ログなど)を適用したい場合、ハンドラーをラップする再利用可能な関数を作成できます:

// lib/with-auth.ts
import { NextRequest } from 'next/server';

type Handler = (req: NextRequest, context?: any) => Promise<Response>;

export function withAuth(handler: Handler): Handler {
  return async (req, context) => {
    const token = req.cookies.get('token')?.value;
    
    if (!token) {
      return new Response(
        JSON.stringify({ error: 'Unauthorized' }),
        {
          status: 401,
          headers: { 'Content-Type': 'application/json' },
        }
      );
    }
    
    // 認証されている場合、元のハンドラーを呼び出し
    return handler(req, context);
  };
}

8. デプロイメントと「SPAモード」の考慮事項

8.1 標準Node.jsデプロイメント

next startを使用した標準のNext.jsサーバーデプロイメントでは、Route Handlers、Server Components、Middlewareなどの機能を使用でき、動的なリクエスト時情報を活用できます。追加の設定は不要です。

8.2 SPA/静的エクスポート

Next.jsは、サイト全体を静的なSingle-Page Application(SPA)として出力することもサポートしています:

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

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

export default nextConfig;

静的エクスポートモードでは、Next.jsは純粋に静的なHTML、CSS、JSを生成します。サーバーサイドコード(APIエンドポイントなど)は実行できません。

8.3 VercelでのAPIデプロイ

Next.jsアプリケーションをVercelにデプロイする場合、APIのデプロイに関するガイドがあります。これには、Vercel Firewallを通じたプログラマティックなレート制限などの他のVercel機能も含まれます。

9. APIエンドポイントの作成をスキップするタイミング

App RouterのReact Server Componentsを使用すると、パブリックエンドポイントを公開することなく、サーバー上で直接データをフェッチできます:

// app/users/page.tsx
// (Server Component)
export default async function UsersPage() {
  // このフェッチはサーバー上で実行される(クライアントサイドコードは不要)
  const res = await fetch('https://api.example.com/users');
  const data = await res.json();
  
  return (
    <main>
      <h1>Users</h1>
      <ul>
        {data.map((user: any) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </main>
  );
}

データがNext.jsアプリ内でのみ使用される場合、パブリックAPIは全く必要ないかもしれません。

10. すべてをまとめる

  1. 新しいNext.jsプロジェクトを作成:npx create-next-app@latest --api
  2. app/ディレクトリ内にRoute Handlersを追加(例:app/api/users/route.ts
  3. 同じファイルでHTTPメソッド(GETPOSTPUTDELETEなど)をエクスポート
  4. Web標準APIを使用してRequestオブジェクトと対話し、Responseを返す
  5. 他のクライアントがデータを消費する必要がある場合、またはバックエンドサービスをプロキシする場合は、パブリックAPIを構築

結論

Next.jsのRoute Handlersは、モダンなWeb標準を活用してAPIを構築するための強力で柔軟な方法を提供します。プロキシレイヤーから完全なAPIまで、様々なユースケースに対応できます。

よくある質問

Server Actionsについてはどうですか?

Server ActionsはフォームやミューテーションのためのNext.js固有の機能で、Route Handlersと組み合わせて使用できます。

Route HandlersでTypeScriptを使用できますか?

はい、Route HandlersはTypeScriptを完全にサポートしており、型安全性を提供します。

認証のベストプラクティスは何ですか?

JWT、セッション、またはサードパーティ認証プロバイダーを使用し、適切なミドルウェアパターンを実装することが推奨されます。