redirect の使い分け。307 と 308、どこで転送するか
Next.js の転送は、redirect・permanentRedirect・next.config の redirects・proxy の4つがあり、返す状態コードと動く時点が違います。
4つの転送と、返す状態コード
同じ /b へ転送するページを4通りで作り、状態コードを確かめました。
| 書き方 | 状態コード | 動く時点 |
|---|---|---|
| redirect('/b') | 307 | ページを描くとき |
| permanentRedirect('/b') | 308 | ページを描くとき |
| next.config の redirects(permanent: false) | 307 | ページを描く前 |
| next.config の redirects(permanent: true) | 308 | ページを描く前 |
| proxy の NextResponse.redirect | 307 | ページを描く前 |
307 は「一時的に移っている」、308 は「ずっと移った」という意味です(MDN の状態コードの説明)。URL を変えて、元に戻す予定が無いなら 308 にします。
ページの中で決まるなら redirect
ログインしていない人を入口へ送る、のように、ページのデータを見てから決める転送は redirect を使います。
import { redirect } from 'next/navigation'
export default async function Page() {
const user = await getUser()
if (!user) redirect('/login')
return <p>ようこそ</p>
}
実機で、ビルドのときに描くページでも、開かれたときに描くページでも、307 で転送されました。ビルドのときに描いたページは、転送先と 307 がビルドの成果物に記録されます。
URL を変えたなら next.config の redirects
ページの中身に関係なく、この URL は、あの URL へと決まっている転送は、next.config.ts に書きます。
const nextConfig: NextConfig = {
async redirects() {
return [
{ source: '/old', destination: '/new', permanent: true },
]
},
}
実機で、permanent: true なら 308、false なら 307 でした。ページを描く前に転送されるので、転送元のページのファイルは要りません。
条件で振り分けるなら proxy
Cookie の有無で振り分けるなど、ページを描く前に、リクエストを見て決めたい転送は proxy で書けます(proxy(旧 middleware)の書き方)。
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server'
export function proxy(req: NextRequest) {
if (req.nextUrl.pathname === '/px') {
return NextResponse.redirect(new URL('/b', req.url))
}
return NextResponse.next()
}
実機では 307 でした。ただし proxy での振り分けは体験のためのもので、見せたくないページを守る役目は、ページの側で確かめます(認証の解説)。
Server Action とイベントハンドラ
ここは公式ドキュメントの記述です。
- Server Action の中の
redirect:JavaScript が動いていればブラウザ側の画面移動になり、JavaScript が無いフォーム送信では 303 を返す - ボタンを押したときの処理(イベントハンドラ):
redirectは使えない。next/navigationのuseRouterのpushを使う
選び方
- URL が変わっただけで、条件が無い → next.config の
redirects(ずっとならpermanent: true) - リクエストを見て、描く前に振り分けたい → proxy
- ページのデータを見てから決めたい →
redirect(ずっとならpermanentRedirect) - ボタンを押したあとに移動したい →
useRouterのpush
出典
- nextjs.org/docs/app/guides/redirecting
- nextjs.org/docs/app/api-reference/functions/redirect
- nextjs.org/docs/app/api-reference/functions/permanentRedirect
- developer.mozilla.org/docs/Web/HTTP/Status/308
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。