🔖

Next.jsでMiddlewareが大量に実行される場合の対処法

2024/03/27に公開
1

Next.jsでWEBアプリケーションを開発している時に、middlewareが大量に叩かれるという問題が発生した。

Supabaseを使用しており、middlewareでgetUser()が大量に叩かれ、SupabaseのLimitを食らっていた。

環境

  • Vercel
  • Supabase
  • Next.js(14.x) App Router

解決方法

① PreFetchではMiddlewareをパスするように設定

<Link>を使用していると、prefetchが行われるため、リストページなどでは大量にmiddlewareが実行される。

RLSを導入しているので、ログインしていなければ、ログインページにリダイレクトされればOK。

middleware.ts
export async function middleware(req: NextRequest) {
    ...
}

// Ensure the middleware is only called for relevant paths.
export const config = {
  matcher: [
    {
      source: "/((?!api|_next/static|_next/image|favicon.ico).*)",
      missing: [
        { type: "header", key: "next-router-prefetch" },
        { type: "header", key: "purpose", value: "prefetch" },
      ],
    },
  ],
};

② 静的画像はmiddlewareをパスするように設定

コンポーネントのファイル内に画像を入れていると画像が呼び出される度にmiddlewareが実行されてしまう。
①のsourceで解決していると考えていたが、middlewareが動いてしまうらしい。
そのため、明示的にmiddlewareのpathnameの最後が画像系の場合は、次の処理に進ませないで処理を終了させるようにしたところ、

middleware.ts
export async function middleware(req: NextRequest) {
  const { pathname } = req.nextUrl;

  // 画像ファイル系は処理をしない
  if (
    pathname.endsWith(".svg") ||
    pathname.endsWith(".ico") ||
    pathname.endsWith(".jpg") ||
    pathname.endsWith(".jpeg") ||
    pathname.endsWith(".png") ||
    pathname.endsWith(".gif") ||
    pathname.endsWith(".webp")
  ) {
    return NextResponse.next();
  }
    ...
}

上記の二つで、middlewareが1ページで複数回実行される問題は解決した。
なにかあれば追記します。

2024/11/04:少しだけコードを修正

SasaTech Engineer Blog

Discussion

ninonino

同じ問題に苦しんでいたのでとても助かりました。ありがとうございます!