proxy(旧 middleware)の書き方と、名前が変わった理由
Next.js 16 では middleware という名前が非推奨になり、proxy という名前に変わりました。
検索して出てくる記事は、ほぼ全部が古い名前
「next.js middleware」で調べると、ほぼすべての記事が middleware.ts を書けと言います。Next.js 16 では、その名前は非推奨です。
実機で確かめました。middleware.ts のままビルドすると、こう出ます。
⚠ The "middleware" file convention is deprecated. Please use "proxy" instead.
npx @next/codemod@canary middleware-to-proxy .
基本の形
proxy.ts はプロジェクトの根(app と同じ階層)に置き、proxy という名前の関数を書きます。よく使う3つの動きを1つにまとめた例です。
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server'
export function proxy(request: NextRequest) {
// URL はそのままで、別のページの中身を返す
if (request.nextUrl.pathname.startsWith('/old-blog')) {
return NextResponse.rewrite(new URL('/blog', request.url))
}
// Cookie が無ければ入口へ
if (!request.cookies.has('session')) {
return NextResponse.redirect(new URL('/login', request.url))
}
// そのまま通して、応答にヘッダーを足す
const response = NextResponse.next()
response.headers.set('x-from-proxy', 'yes')
return response
}
export const config = {
matcher: ['/dashboard/:path*', '/old-blog/:path*'],
}
| 開いた URL | 結果 |
|---|---|
| /dashboard(Cookie なし) | 307 で /login へ |
| /dashboard(Cookie あり) | 200。応答に x-from-proxy: yes |
| /old-blog/x | 200。URL はそのまま、中身は /blog |
| /about(matcher の外) | proxy は動かない。ヘッダーも付かない |
返すものは3種類です。NextResponse.next() で通す、redirect で別の URL へ移す、rewrite で URL を変えずに別の中身を返す。転送の状態コードの違いはredirect の使い分けにまとめています。
名前が変わっただけではない
なぜ変わったのかを知っておくと、使い方も迷わなくなります。
この仕組みは、要求が届いたあと、ページに渡る前に挟まるものです。できることは中心的に2つで、書き換えと行き先の変更です。
| やりたいこと | 向いているか | 理由 |
|---|---|---|
| ログインしていない人を入口へ飛ばす | できる | 行き先を変えるだけ |
| 言語や地域で出し分ける | できる | 行き先を変えるだけ |
| ヘッダを足す | できる | 書き換えるだけ |
| 本人かどうかを厳密に判断する | できない | そこで完結させない |
| DB を見て中身を組み立てる | できない | ページ側の仕事 |
「中間の処理」というより「前に立つ取り次ぎ」です。実態に名前を寄せたのが proxy という呼び名です。
書き換え
ファイル名と関数名が変わります。中身の考え方は同じです。
export function middleware() { return NextResponse.next() }
ビルドのたびに告知が出る。
export default function proxy() { return NextResponse.next() }
告知は出ない。実機で確認ずみ。
公式の書き換えの道具が案内されます。手で作るより確実です。
npx @next/codemod@canary middleware-to-proxy .
掛ける範囲は matcher で狭める
export const config = { matcher: ['/about/:path*'] }
書き方はビルドの時点で固定の形に変換されます。実行時に組み立てるものではないので、変数や計算結果は入れられません。
形が違えばビルドで止まります。実機の文言です。
/proxy contains invalid middleware config: source must start with / at "matcher[0]"
先頭のスラッシュは補われません。何番目の指定かまで出るので、直す場所はすぐ分かります。
認可をここで完結させない
ログインが要る画面を守るとき、ここで飛ばすのは体験を良くするためであって、守るためではありません。
- Serverproxy でおおまかに振り分ける
Cookie が無ければ入口へ。速くて安い。
- Serverページやデータ取得で本人を確かめる
ここが本当の守り。飛ばしそこねても、ここで止まる。
- ServerServer Function でも同じ判断をする
画面を通らずに直接呼ばれても、ここで止まる。
判断を1か所に集めたくなりますが、集めるなら手前ではなく奥です。手前は迂回され得ます。実際に動いているものが最小構成のログインにあります。
まとめ
- Next.js 16 で
middlewareは非推奨。proxyが正式な名前 - ビルドは通る。だから気づかないまま残る
- 両方置くとビルドが落ちる。残すのではなく履歴から戻す
matcherはビルド時に固定。変数は入れられない。先頭のスラッシュは必須- 認可をここで完結させない。守りは奥に置く
出典
- nextjs.org/docs/messages/middleware-to-proxy
- nextjs.org/docs/app/api-reference/file-conventions/proxy
- nextjs.org/docs/app/guides/upgrading/version-16
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。