ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
この記事の要点
route.tsを置くと、そのパスが API エンドポイントになる。中身は Web 標準のRequestとResponse。- 扱えるメソッドは
GETPOSTPUTPATCHDELETEHEADOPTIONS。それ以外は 405 が返る。 - 同じ階層に
page.tsxとroute.tsは置けない。API は別パスに切る。 - Route Handlers は既定でキャッシュされない。
GETだけは設定でキャッシュに乗せられる。 - リクエスト全体に共通処理を挟みたい場合は
proxy.ts。バージョン 16 でmiddlewareから改名された。
画面の中でデータを更新するだけなら Server Functions で足ります。しかし、外部サービスからの Webhook を受ける、モバイルアプリに JSON を返す、CSV をダウンロードさせる、といった用途では独立したエンドポイントが必要です。それを担うのが Route Handlers です。
1もっとも小さな API
app の中に route.ts を置き、HTTP メソッド名の関数をエクスポートします。
// app/api/hello/route.ts
export async function GET(request: Request) {
return Response.json({ message: 'hello' })
}
これで /api/hello に GET すると JSON が返ります。特別なフレームワーク独自のオブジェクトはなく、引数も戻り値もブラウザでおなじみの Web 標準 API です。
ファイルの置き場所のルールは page.tsx と同じで、フォルダ階層がそのまま URL になります。ただし同じ階層に page.tsx と route.ts を同居させることはできません。1 つのパスに対する扱いは、どちらか一方が全 HTTP メソッドを引き受ける形になるためです。
| ページ | ルート | 結果 |
|---|---|---|
app/page.tsx | app/route.ts | 競合してビルドできない |
app/page.tsx | app/api/route.ts | 問題なし |
app/[user]/page.tsx | app/api/route.ts | 問題なし |
2メソッドごとに書き分ける
1 つのファイルに複数のメソッドを並べられます。定義していないメソッドで呼ばれた場合は 405 Method Not Allowed が自動的に返ります。
// app/api/posts/route.ts
export async function GET() {
const posts = await db.posts.findMany()
return Response.json(posts)
}
export async function POST(request: Request) {
const body = await request.json()
const created = await db.posts.create(body)
return Response.json(created, { status: 201 })
}
Next.js は標準の Request と Response を拡張した NextRequest / NextResponse も提供しています。Cookie の読み書きなど、少し込み入った処理を書くときに便利です。
3URL に含まれる値を受け取る
動的セグメントを使う場合、値は第 2 引数のコンテキストから取り出します。ここも Promise なので await が必要です。
// app/users/[id]/route.ts
import type { NextRequest } from 'next/server'
export async function GET(_req: NextRequest, ctx: RouteContext<'/users/[id]'>) {
const { id } = await ctx.params
return Response.json({ id })
}
RouteContext はグローバルに使える型ヘルパーで、next dev や next build の際に自動生成されます。インポートは不要です。
4キャッシュの扱い
Route Handlers は既定ではキャッシュされません。GET だけは、設定を書けば静的な応答として扱えます。
// app/items/route.ts
export const dynamic = 'force-static'
export async function GET() {
const res = await fetch('https://api.example.com/items')
const data = await res.json()
return Response.json({ data })
}
同じファイルに書いた他のメソッドはキャッシュされません。副作用を伴う POST などがキャッシュされないのは当然の設計です。
Cache Components を有効にしている場合、GET の扱いは通常のページと同じモデルになります。リクエスト依存の値に触れなければ事前生成され、触れた時点でリクエスト時実行に切り替わります。
なお、'use cache' をハンドラ本体に直接書くことはできません。ヘルパー関数に切り出して、そちらに付けます。
// app/api/products/route.ts
import { cacheLife } from 'next/cache'
export async function GET() {
const products = await getProducts()
return Response.json(products)
}
async function getProducts() {
'use cache'
cacheLife('hours')
return await db.query('SELECT * FROM products')
}
5Server Functions との使い分け
自分のアプリの画面から呼ぶ更新処理。フォーム送信、ボタン操作。URL を公開する必要がない。
外部から呼ばれるもの。Webhook 受信、他システム連携、モバイルアプリ向け API、ファイルの生成と配信。
判断の軸は「呼び出し元が自分の画面かどうか」です。自分の画面からしか呼ばないのに API を作ると、URL とスキーマを維持する手間だけが増えます。
6特別な役割を持つファイル
sitemap.ts、robots.ts、opengraph-image.tsx、icon.tsx なども内部的には Route Handlers ですが、これらはリクエスト時の API や動的な設定を使わない限り静的に生成されます。詳しくは メタデータ API で SEO を整える で扱います。
7全リクエストに共通処理を挟む — proxy.ts
認証チェックやリダイレクトのように、ルートに入る前の段階で処理したいことがあります。従来 middleware.ts と呼ばれていたこの仕組みは、バージョン 16 で proxy.ts に改名されました。
// proxy.ts(プロジェクトのルートに置く)
export function proxy(request: Request) {
// 認証チェック、リダイレクト、書き換えなど
}
関数名も proxy にします。設定フラグの名前も変わっており、たとえば skipMiddlewareUrlNormalize は skipProxyUrlNormalize になりました。改名は移行用のコードモッドで自動処理できます。
注意点として、proxy の実行環境は Node.js に固定されており、変更できません。Edge ランタイムを使い続ける必要がある場合は、当面 middleware のまま運用することになります。
8つまずきやすいところ
page.tsxと同じ場所に置いてビルドが落ちる:/api以下など、別のパスに切り出します。- 404 になる:ファイル名が
route.tsかどうか、エクスポートした関数名が大文字のメソッド名かどうかを確認します。 - 認証を忘れる:Route Handlers は公開エンドポイントです。ハンドラの冒頭で必ず権限を確認します。
- キャッシュされていると思い込む:既定ではされません。負荷を減らしたいなら明示的に設定します。
- 古い記事の
pages/api:Pages Router 時代の API Routes です。App Router では Route Handlers を使い、併用する必要はありません。
バックエンド側の口が用意できたら、次は公開品質を整える工程に入ります。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 Spring Frameworkのアノテーション一覧
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- PHPでのファイルアップロード方法|multipart/form-dataと$_FILES 2026-08-07 17:15:57
- PHP $_SERVERとは|DOCUMENT_ROOT・PHP_SELFなど主な要素 2026-08-07 17:15:57
- Scratchのアカウントの作り方|メールアドレスとユーザー名の登録手順 2026-08-07 17:15:57
- djangoにおけるMVCアプリケーション実装例 2026-08-07 17:15:57
- Bluetoothとは|仕組み・BLEとClassicの違い・用途 2026-08-07 17:15:57
- Spring Bootのテスト入門|@SpringBootTestとJUnitでの単体・結合テスト 2026-08-07 17:15:57
- Java とは?言語仕様・JVM・主要フレームワーク一覧 2026-08-07 17:15:56
- インストール方法(Windows版) 2026-08-07 17:15:56
- APIキー取得方法 2026-08-07 17:15:56
- 【PHPフレームワーク】Laravelの使い方 2026-08-07 17:15:56
- Scratch 作品の公開方法 2026-08-07 17:15:56
- Google OAuth 2.0 認証の実装方法 2026-08-07 17:15:56
- データベースとは?RDB / NoSQL / SQL の基礎 2026-08-07 17:15:56
- インストール(eclipseプラグイン) 2026-08-07 17:15:56
- Spring Frameworkの使い方 2026-08-07 17:15:56
コメントを削除してもよろしいでしょうか?