Next.js の middleware が実行されない
middleware.ts はプロジェクトルートに 1 ファイル限定で、matcher の設定と Edge runtime 制約に従う必要がある。
配置・matcher・export 名のどれかがずれると静かにスキップされる。
#nextjs#middleware#matcher#edge#routing
公開:
要約
middleware.ts が動かないときは「ファイルの場所」「matcher」「export 名」「Edge runtime 制約」を順に疑う。
公式の Middleware のとおり、middleware は プロジェクトルートに 1 ファイルしか置けず、複数置いても認識されない。
よくある原因
- 配置場所が間違っている:
app/middleware.tsやpages/middleware.tsは無効。
プロジェクトルート、またはsrc/を使う構成ならsrc/middleware.ts - matcher が狭すぎる:
matcher: "/api/:path*"だけだと通常ページで実行されない - export 名のミス:
myMiddlewareのような任意名で export しても認識されない - Edge runtime 非対応 API を使用:
fs.readFileSyncなどを呼ぶと middleware ごと落ち、結果として実行されていないように見える
解決策
1. ルート配置を確認
my-app/
├── app/
├── src/ # src ディレクトリを使う場合
│ ├── app/
│ └── middleware.ts # ← ここ
├── middleware.ts # ← または ここ(src を使わない場合)
└── next.config.jsapp/middleware.ts ではない点に注意。
2. matcher を適切に書く
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(req: NextRequest) {
return NextResponse.next();
}
export const config = {
matcher: [
"/((?!api|_next/static|_next/image|favicon.ico).*)",
],
};API ルートや静的アセットを除外しつつ全ページに効かせるテンプレ。
複数の matcher を配列で並べてもよい。
3. export 名は middleware
関数名は middleware 固定。
export function middleware(req: NextRequest) { /* ... */ }
// あるいは
export default function (req: NextRequest) { /* ... */ }auth や myMiddleware といった名前にすると、Next.js は middleware として扱わない。
4. Edge runtime で動く API のみ使う
middleware は Edge runtime で実行される。fs / child_process / Node.js 専用ストリーム等は使えない。
重い処理や DB アクセスは Route Handler 側で行い、middleware は認証ヘッダの検査やリダイレクト判定に限定する。
export function middleware(req: NextRequest) {
const token = req.cookies.get("session")?.value;
if (!token) {
return NextResponse.redirect(new URL("/login", req.url));
}
return NextResponse.next();
}dev サーバを再起動して console.log がターミナルに出れば動いている合図。