Next.js 跳转全家桶:redirect、permanentRedirect、NextResponse.redirect 与更多
在 Next.js(App Router)里,「跳转」并不是只有一把钥匙。
不同的 API 在「运行位置、HTTP 状态码、SEO 语义、回退行为」上差异巨大。
本文把官方 4 种写法 + 中间件用法整理成一张速查表,并给出实战代码,让你 3 分钟选对 API。
1 四把钥匙速查表
| API | 触发位置 | HTTP 状态 | SEO 语义 | 能否回退 | 典型场景 |
|---|---|---|---|---|---|
redirect('/new') |
Server Component / Route Handler | 307 临时 | 暂时转移 | ✅ | 登录校验、动态路由 |
permanentRedirect('/new') |
Server Component / Route Handler | 308 永久 | 永久搬家 | ❌ | 域名迁移、旧路由废弃 |
NextResponse.redirect('/new') |
middleware.js | 307/308/301…(可传) | 同上 | 同上 | 请求到达前统一拦截 |
<Link href="/new"> 或 useRouter().push() |
浏览器 | 200(SPA 内) | 不触发重定向 | ✅ | 前端导航、无刷新 |
2 代码一图胜千言
2.1 服务端 307 / 308
ts
// app/order/[id]/page.tsx
export default async function Page({ params }) {
const valid = await checkOrder(params.id);
if (!valid) {
redirect('/404'); // 307
}
return <Order />;
}
ts
// app/old-blog/[slug]/page.tsx
export default function Page() {
permanentRedirect('/blog/new-slug'); // 308
}
2.2 中间件统一拦截
ts
// middleware.ts
import { NextResponse } from 'next/server';
export function middleware(request) {
const token = request.cookies.get('auth')?.value;
// 未登录全部跳到登录页
if (!token) {
return NextResponse.redirect(new URL('/login', request.url), 307);
}
// 已登录但访问旧域名
if (request.nextpathname.startsWith('/old')) {
return NextResponse.redirect(new URL('/new', request.url), 308);
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
3 什么时候选哪一个?
| 需求 | 推荐 API |
|---|---|
| 登录页校验后跳转 | redirect() |
| 旧域名永久迁移 | permanentRedirect() |
| 统一鉴权 / A/B / 多域名重定向 | NextResponse.redirect() |
| 前端按钮、菜单 | <Link> 或 useRouter().push() |
4 小结一句话
渲染层用
redirect/permanentRedirect,网络层用NextResponse.redirect,交互层用<Link>;选对位置,状态码和 SEO 就自然正确。
![[Next.js篇] Next.js 跳转全家桶:redirect、permanentRedirect、NextResponse.redirect 与更多](/_next/image?url=https%3A%2F%2Fpic.netbian.com%2Fuploads%2Fallimg%2F250819%2F155850-17555903305b13.jpg&w=3840&q=75)