困った共通処理
Next.js で、全ページ共通の処理がある場合、あんまり頭のよくないコードを書くことになります。
pages/index.js
export const getServerSideProps = async (ctx) => {
// (全ページ共通処理)共通情報を取得する。
let commonInfo;
try {
commonInfo = await getCommonInfo();
} catch (exception) {
// 取得できなければ404で返す
ctx.res.status = 404;
return { props: { notFound: true } };
}
// いろいろな処理…
}
これを全ページにコピペして書くなんて信じられな〜い!
もちろん関数に抽出すればもっと短くなるかもしれないけど、 try { } catch () { return ... }
は短くならないでしょう。
ミドルウェアとして共通処理を括りだす
そういうことで、共通処理を下記のようにミドルウェア(middleware - 関数を引数にとって関数を返す関数)として抽出してあげましょう。
utils/addCommonInfo
export const addCommonInfo = (f) => async (ctx) => {
// 共通情報を取得する。
try {
// ctx.commonInfo に共通情報を入れてあげる
ctx.commonInfo = await getCommonInfo();
return await f(ctx);
} catch (exception) {
// 取得できなければ404で返す。
ctx.res.status = 404;
return { props: { notFound: true } };
}
}
// ※こういう共通処理のファイルはくれぐれも `pages/` 配下におかないように。 `next build` がよくわからないメッセージとともに失敗する原因になります。
抽出した関数を使うようにしてあげましょう。もともとのgetServerSidePropsの関数を包めばOKです。
pages/index.js
import { addCommonInfo } from "../utils/addCommonInfo"
export const getServerSideProps = addCommonInfo(async (ctx) => {
// 共通情報
const {commonInfo} = ctx
// いろいろな処理…
})
こういったミドルウェアがいくつかある場合は、ミドルウェアの塊になるミドルウェアを作るのも手です。
utils/addStandardMiddlewares.js
export const addStandardMiddlewares = (f) => addCommonInfo(
addCommonInfo2(
addCommonInfo3(f)))
もちろん Next.js を組み込む側のサーバをセットアップしてあげて、そこにミドルウェアを入れるのも手ですが、こちらのアプローチの方がNext.jsのレンダリング機構を利用することができます。ただ、全ページの関数に関数をミドルウェアで装飾するコードは書く必要は出てきます。要は使い分けですね。