appDir の Route Handlers を使う・API Routes からの変更点

2023-04-22

公式ドキュメント
Routing: Route Handlers | Next.js

これまで pages directory では例えば /pages/api/hello.ts を作成して以下のように書いていましたが、

pages/api/hello.tsexport default function handler(req, res) {
  res.json({ msg: 'Hello world!' });
}

app directory で同じことをする場合は、/app/hello/route.ts を作成して以下のように書きます。

app/hello/route.tsexport function GET(req) {
  return new Response('Hello world!');
}

それぞれのインターフェース変更についての細かい意思決定プロセスは全く追っていませんが、ひとまず表面的には以下のような変更があります。

1. 特定のメソッドに対してのハンドラを named export するようになった

2. ファイルを置く場所が変わった

3. ハンドラの API が変わった

これまで全ての HTTP method に default export されたハンドラが割り当てられていましたが、GETPOST のように特定のメソッドに対してのハンドラを named export するように変更されました。
Supported HTTP Methods | Next.js

大抵 (というか全て) API は特定の method のみを想定しているはずなので、これまで実装者は以下のような分岐を書く必要がありました。

export default function handler(req, res) {
  if (req.method !== 'POST') {
    res.status(403).json({ error: 'Method not allowed' });
  }
}

これを愚直に書いていたか、ある程度共通化していたか、うまいことミドルウェアを噛ませていたかはさておき、単純に嬉しい update かと思います。

app directory 自体の変更と言えますが、ファイルを置く場所が /pages/api/**/*.tsx から、/app/**/route.tsx に変わりました。
例えば /api/posts のエンドポイントはこれまで /pages/api/posts/index.tsx に置いていたファイルは、/app/posts/route.tsx に置くようになります。

これまでの NextApiHandler は比較的 express like で、reqres を受け取り、res.json() などでレスポンスしていました。
Route Handlers ではよりローレベル / ブラウザネイティブな API が露出していて、Fetch API の Request を受け取り、関数から Fetch API の Response を返します。

ただし、より easy に Next.js がラップした便利 req: NextRequestres: NextResponse を引き続き使うこともできるそうです。
Extended NextRequest and NextResponse APIs | Next.js

以下は Next.js の docs から引用しました。

export async function GET(request: NextRequest) {
  const token = request.cookies.get('token');
  const response = NextResponse.next();
  response.cookies.set('token', token);
  return response;
}

大体こんな感じでしょうか?