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