🐾

Next.jsのmiddlewareを本番と開発で切り替える

に公開

背景

  • middleware.tsを本番と開発環境で別の内容にする必要があった
  • 今までは開発環境のBasic認証にのみ使っていた。新たにリダイレクトの処理を入れるため、middlewareを環境によって分ける必要が出てきた
  • 本番環境でのmiddlewareの発火を抑えることも課題だったのでmatcherの記述も追加した

課題

  • middleware.tsは1ファイルしかデプロイできない
  • matcherを開発と本番で切り替えたいが、process.env.NODE_ENVのような環境による切り替えができない

解決法

  • middleware.tsmiddleware-for-production.tsを分けて管理
  • 本番ビルド時のみ for-productionmiddleware.ts にコピーして差し替え
.github/workflows/deploy.yml
- name: Replace middleware.ts for Production
  if: ${{ inputs.production == true }}
  run: |
    rm src/middleware.ts
    cp src/middleware-for-production.ts src/middleware.ts

matcherの工夫

  • 開発版(全体にマッチ)
    開発環境ではBasic認証をサイト全体にかけるため、全体にマッチする書き方にする。
middleware.ts
export const config = {
  matcher: [
    "/((?!api|_next/static|_next/image|favicon.ico).*)",
  ],
}
  • 本番版(検索クエリがある場合のみマッチ)
    本番環境では、検索ページ/searchにおいて、特定の検索条件が存在する場合のみmiddlewareを発火させたい要件があった。
    そのため、matcherを以下のように記述した。
middleware-for-production.ts
export const config = {
  matcher: [
    { source: "/search(.*)", has: [{ type: "query", key: "category" }] },
    { source: "/search(.*)", has: [{ type: "query", key: "location" }] },
    { source: "/search(.*)", has: [{ type: "query", key: "type" }] },
  ],
};

まとめ

  • middlewareはファイルを分けて管理することで、開発・本番で挙動を変えられる
  • matcherの設定は、クエリパラメータの有無まで柔軟に制御できる
  • matcherを設定することによりmiddlewareの発火を最低限に抑えることができる
  • GitHub Actionsで差し替えを自動化すれば安全に運用可能
chot Inc. tech blog

Discussion