Next.jsでAPIのエンドポイントを組む際はnext-connectを使うと良いよ
2021-12-09
Next.js で API のエンドポイントを組むの場合、なかなかしっくり来る組み方に出会えていませんでした。
そんな中 [next-connect] を使ってみると、かなりしっくり来る組み方ができたので紹介をば。
まずは Next.js の 公式ドキュメント に沿ってみるとこんな感じになります。
function handler(req, res) {
const { method } = req;
const { idToken } = nookies({ req });
// idToken のあれこれ
if (method === "GET") {
// GET のあれこれ
res.status(200).json({ hoge: "hoge" });
} else if (method === "POST") {
// POST のあれこれ
res.status(200).json({ fuga: "fuga" });
}
}
export default handler;
上記を見ると悪くなさそうに見えるのですが、TypeScript となるとそうもいきません。
import type { NextApiRequest, NextApiResponse } from "next";
type GetData = {
hoge: string;
};
type PostData = {
fuga: string;
};
function handler(
req: NextApiRequest,
res: NextApiResponse<GetData | PostData>,
) {
const { idToken } = parseCookies({ req });
const { method } = req;
// idToken のあれこれ
if (method === "GET") {
// GET のあれこれ
res.status(200).json({ hoge: "hoge" });
} else if (method === "POST") {
// POST のあれこれ
res.status(200).json({ fuga: "fuga" });
}
}
export default handler;
結構ごちゃついてくる印象がありますが、いかがでしょうか。
で、これを next-connect を使って書き換えるとこんな感じになります。
import type { NextApiRequest, NextApiResponse } from "next";
import nc from "next-connect";
type GetData = {
hoge: string;
};
type PostData = {
fuga: string;
};
const handler = nc<NextApiRequest, NextApiResponse<GetData | PostData>>().use(
// ここを middleware として共通化しても良い
(req, _, next) => {
const { idToken } = parseCookies({ req });
// idToken のあれこれ
next();
},
);
type ExtendedGetRequest = Record<string, never>;
type ExtendedGetResponse = {
json(body: GetData): void;
};
handler.get<ExtendedGetRequest, ExtendedGetResponse>(
// 型をつけなくても良い
async (_, res: NextApiResponse<GetData>) => {
// GET のあれこれ
res.status(200).json({ hoge: "hoge" });
},
);
type ExtendedPostRequest = Record<string, never>;
type ExtendedPostResponse = {
json(body: PostData): void;
};
handler.post<ExtendedPostRequest, ExtendedPostResponse>(
// 型をつけなくても良い
async (_, res: NextApiResponse<PostData>) => {
// POST のあれこれ
res.status(200).json({ fuga: "fuga" });
},
);
export default handler;
もちろん get と post の処理をそのままチェーンで繋ぐことも可能です。
で、next-connect のもっとも大きいメリットが、use の引数を middleware として共通化することも可能な点です。
他にもエラーハンドリングの書きっぷりも強いですし、共通化にも対応しているのがすごいですね。
さらに getServerSideProps でも呼び出し可能なので、middleware をすべて共通化すると良い感じです。
ということで、今後はこれを使って書いていこうかなーと思います。