Route Handlers入門
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 を利用するにあたって、いくつか守るべきルールがあります。以下では主なポイントを挙げます。
-
route.jsとpage.jsx(または.tsx) の 2 ファイルが主役-
page.jsxは画面ページ用 -
route.jsは API のエンドポイント用
-
-
route.jsとpage.jsxは同階層に置かない
同じディレクトリ内にroute.jsとpage.jsxを併存させることは避けるべきです。API 専用のapiディレクトリを用意し、その直下にroute.jsを配置する方法が推奨されます。 -
両ファイルともに
appフォルダ以下に配置する
App Router が有効なプロジェクトでは、appディレクトリがルートとして扱われるため、これに準拠する必要があります。 -
default exportは不要
Route Handlers では、export defaultではなく、HTTP メソッド名(GET,POST,PUT,DELETEなど)の関数をエクスポートする形式を取ります。 -
関数名をメソッド名と同一にする
たとえば、GETメソッドならexport function GET() { ... }のように宣言します。 -
レスポンスは
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;
}
Cookie の読み取りと設定
next/headers から Cookie を扱う例
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}` },
});
}
NextRequest から直接 Cookie を読み取る例
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/navigation の redirect 関数を使用します。
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 });
}
参考リンク
以上です。
Discussion