LoginSignup
9
6

More than 3 years have passed since last update.

小ネタ: Next.js のサーバサイド側の共通処理を括り出したい (Middlewareパターン)

Last updated at Posted at 2020-06-08

困った共通処理

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のレンダリング機構を利用することができます。ただ、全ページの関数に関数をミドルウェアで装飾するコードは書く必要は出てきます。要は使い分けですね。

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6