😎

Route Handlers入門

2025/01/22に公開

Next.js Route Handlers について

Next.js 13 系以降で登場した App Router では、従来の pages ディレクトリを介したルーティングとは異なる、新たなルーティング方法が導入されています。そんな中で、API エンドポイントを簡単に設計できる仕組みとして登場したのが Route Handlers です。ここでは、Route Handlers の概要や使い方、ルールなどを紹介します。


概要

Next.js が App Router をリリースした後、画面遷移用のルートAPI エンドポイント用のルートを分離してよりわかりやすく管理するための仕組みとして、route.js(または route.ts) を使用した Route Handlers が登場しました。特に GET メソッドのキャッシュ機能が強力な特徴で、リクエスト情報を参照しない限り、デフォルトでキャッシュが有効になる点が大きなメリットです。

  • App Router の後に登場
    App Router はディレクトリ構造を用いてルーティングを行う仕組みですが、それに付随して API エンドポイントの記述も同じ構造内でシンプルに定義できるようになりました。
  • 簡単に API 設計が可能
    従来の pages/api ディレクトリを利用する方法と比べて、関連するページと同じ階層(または近い階層)でエンドポイントを定義できます。
  • GET メソッドのキャッシュ機能
    GET メソッドでリクエスト情報(たとえばヘッダやクッキーなど)を参照しない場合、レスポンスをキャッシュできます。不要であれば無効化する設定も簡単です。

ルール

Route Handlers を利用するにあたって、いくつか守るべきルールがあります。以下では主なポイントを挙げます。

  1. route.jspage.jsx(または .tsx) の 2 ファイルが主役

    • page.jsx は画面ページ用
    • route.js は API のエンドポイント用
  2. route.jspage.jsx は同階層に置かない
    同じディレクトリ内に route.jspage.jsx を併存させることは避けるべきです。API 専用の api ディレクトリを用意し、その直下に route.js を配置する方法が推奨されます。

  3. 両ファイルともに app フォルダ以下に配置する
    App Router が有効なプロジェクトでは、app ディレクトリがルートとして扱われるため、これに準拠する必要があります。

  4. default export は不要
    Route Handlers では、export default ではなく、HTTP メソッド名(GET, POST, PUT, DELETE など)の関数をエクスポートする形式を取ります。

  5. 関数名をメソッド名と同一にする
    たとえば、GET メソッドなら export function GET() { ... } のように宣言します。

  6. レスポンスは NextResponse 型のオブジェクトを明示的に return
    NextResponse(または Response)を返してレスポンスを完結させます。


実装例

次に、実際のコード例を紹介します。以下の例は主に route.js 内での記述を想定しています。なお、TypeScript プロジェクトであれば .tsx / .ts を使用し、型定義を追加しておくとよいでしょう。

キャッシュの有効化/無効化

デフォルトでは GET メソッドのレスポンスに対してキャッシュが有効ですが、以下のようにオプションで制御できます。

export const dynamic = "force-static"; // キャッシュを有効にしたいなら
export const dynamic = "force-dynamic"; // キャッシュを無効にしたいなら

import { NextRequest, NextResponse } from "next/server"; // req, resにそれぞれ型が存在

export function GET(req: NextRequest) {
  const res = NextResponse.json({ msg: "hello,world!" });
  return res;
}
import { cookies } from "next/headers";

export async function GET(request: Request) {
  const cookieStore = cookies();
  const token = cookieStore.get("token");

  return new Response("Hello, Next.js!", {
    status: 200,
    // Set-Cookie ヘッダを使用して新しい Response を返すこともできる
    headers: { "Set-Cookie": `token=${token?.value}` },
  });
}
import { NextRequest } from "next/server";

export async function GET(request: NextRequest) {
  const token = request.cookies.get("token"); // req から cookie を取得
  return new Response(`Your token: ${token?.value}`);
}

ヘッダの読み取りと設定

import { headers } from "next/headers";

export async function GET(request: Request) {
  const headersList = headers();
  const referer = headersList.get("referer");

  return new Response("Hello, Next.js!", {
    status: 200,
    // 新しく header を設定する場合も新しい Response を返す
    headers: { referer: referer || "" },
  });
}

NextRequest から Headers を取り出す例

import { NextRequest } from "next/server";

export async function GET(request: NextRequest) {
  const requestHeaders = new Headers(request.headers);
  // `requestHeaders` に対して操作が可能
  return new Response("Headers Processed");
}

リダイレクト

特定のパスへリダイレクトしたい場合は、next/navigationredirect 関数を使用します。

import { redirect } from "next/navigation";

export async function GET(request: Request) {
  redirect("https://nextjs.org/");
}

クエリパラメータの取得

NextRequest には nextUrl というプロパティがあり、クエリパラメータに簡単にアクセスできます。

import { NextRequest } from "next/server";

export function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const query = searchParams.get("query");
  // 例えば /api/search?query=hello の場合、query には "hello" が入る
  return new Response(`Query is ${query}`);
}

POST メソッドの処理

JSON データの受け取り

export async function POST(request: Request) {
  const res = await request.json();
  return Response.json({ res });
}

FormData の受け取り

request.formData() メソッドを用いてフォームデータを取得できます。

export async function POST(request: Request) {
  const formData = await request.formData();
  const name = formData.get("name");
  const email = formData.get("email");
  return Response.json({ name, email });
}

参考リンク

 
 
 
 

以上です。

KA projects

Discussion