☰
TIL · Next.js 重定向实战:在 next.config.js 中通过 redirects() 定义 URL 跳转(308 与 307)
2026/10/7 2:04:52 网站建设 项目流程
  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载

本篇整理 TIL 仓库中关于 Next.js 应用 URL 重定向的实践:与其把重定向规则写在vercel.json里(它只在 Vercel 部署层生效,本地开发时毫无感知),不如直接写进next.config.js的redirects()异步函数,让next dev本地开发与线上部署行为完全一致。读完你可以掌握redirects()的完整配置写法、permanent字段对 308/307 状态码的控制逻辑,以及如何在本地用curl快速验证跳转是否按预期生效。

为什么要把重定向写进 next.config.js

网站内容总会有迁移的时候:博客文章改名、商品页换路径、旧域名跳新域名。人们早已把旧链接收藏起来或散布在互联网各处,为了不破坏这些 URL,就需要配置重定向规则。

仓库中的姊妹篇 Add Web Server Layer Redirects 介绍了第一种做法:把重定向写进项目根目录的vercel.json,交给 Vercel 的 Web Server 层处理,例如:

{ "redirects": [ { "source": "blog/old-blog-post-name", "destination": "blog/new-blog-post-name" }, { "source": "/store", "destination": "store.example.com" } ] }

第一条规则把站内某个路径重定向到同一域名下的另一个路径;第二条规则把路径重定向到外部 URL。在 Vercel 平台上这些规则默认返回 308 状态码。

但问题在于:vercel.json是在部署时由 Vercel 平台解析的。当你本地运行next dev时,这些规则根本不会被执行,导致"本地访问旧链接 404、部署后却跳转成功"的割裂体验,容易误导开发者,尤其在调试阶段让人困惑。

两种方案的对比:

对比维度vercel.jsonnext.config.js的redirects()
生效层级Vercel 平台 Web Server 层Next.js 应用层(dev server / 构建产物)
本地next dev是否生效否是
状态码控制默认 308通过permanent显式控制 308 / 307
配置格式JSONJavaScript(支持逻辑与动态生成)
与框架耦合度依赖 Vercel 平台纯 Next.js,可移植到任意托管环境

因此,把重定向下沉到next.config.js,是让本地与线上行为保持一致的首选方式。

在 next.config.js 中定义 redirects()

Next.js 允许在next.config.js中通过redirects()异步函数声明重定向规则。当本地运行 Next dev server 时,这些规则就会被处理并生效。

一个完整可运行的最小示例(比原笔记补充了module.exports导出,并对路径规范做了修正):

// next.config.js const nextConfig = { async redirects() { return [ { // 站内路径 → 站内路径:旧博客文章搬到新地址 source: "/blog/old-blog-post-name", destination: "/blog/new-blog-post-name", permanent: true, }, { // 站内路径 → 外部 URL:/store 跳转到独立商城站点 source: "/store", destination: "https://store.example.com", permanent: true, }, ]; }, }; module.exports = nextConfig;

规则对象的核心字段:

字段作用说明
source匹配的请求路径建议以/开头,按 Next.js 的路径匹配约定书写,否则可能产生预期之外的匹配结果
destination跳转目标站内路径建议同样带/;外部地址则写完整 URL(含协议与域名)
permanent是否永久重定向true产生 308,false产生 307(详见下一节)

几点实践要点:

  • redirects()是异步函数,可以return静态数组,也可以在内部做动态计算、按环境变量返回不同规则,灵活性远高于静态 JSON。
  • 配置文件在较新版本中还支持next.config.mjs(ESM)与next.config.ts(TypeScript)形态,核心的redirects()API 保持一致。
  • 重定向规则按数组顺序逐一匹配,第一个命中的规则生效,因此更具体的规则应放在前面。
  • redirects()属于框架层配置,无论页面使用 Pages Router 还是 App Router,请求匹配到source时都会执行跳转。

提示:原笔记示例中部分路径未带前导/,且第二个规则对象缺少分隔逗号。上面给出的版本修正了这两处,可直接复制运行。

permanent: true → 308,false → 307

permanent是决定跳转语义的关键开关,这也是原笔记最核心的结论:

  • permanent: true:规则会被编译为308 Permanent Redirect,告知客户端与搜索引擎"该 URL 已永久迁移",适合旧内容彻底搬家、不再回退的场景;
  • permanent: false:规则会变为307 Temporary Redirect,适合"暂时转移"的场景,例如促销页临时指向活动页、未来还要切回原地址的情况。

308 与 307 都保留了原始请求方法与请求体(这与更常见的 301/302 不同),因此在 POST 等带请求体的场景下语义更安全。当redirects()返回的规则需要调整时,改完配置重启 dev server(或重新构建)即可生效。

匹配规则与进阶参数

除基础的source/destination/permanent之外,按 Next.js 官方 API 约定,redirects()还支持更精细的匹配能力,可按需选用:

  • 路径通配符:source: "/blog/:slug"可匹配任意单段路径;source: "/docs/*"可匹配多段路径,捕获的参数可在destination中以:slug形式回填,适合成批迁移的场景;
  • 条件匹配has/missing:可以基于请求头(header)、Cookie(cookie)、查询参数(query)等条件决定是否触发跳转,适合 A/B 分流、按来源渠道跳转等复杂场景;
  • basePath/locale:在配置了basePath或国际化时,重定向匹配会自动叠加相关前缀,无需在每条规则里重复书写。

同时注意,Next.js 官方约定中headers、redirects、rewrites三类配置存在固定检查顺序:先headers,再redirects,最后rewrites。如果你的请求同时命中了多种配置,需要依据该顺序预判最终行为。

配置层重定向与运行时重定向的分工

next.config.js里的redirects()属于声明式、全局、静态的重定向:规则写死、匹配即跳转,适合内容迁移这类"URL 永久或长期变化"的场景。

但并非所有跳转都适合写进配置文件。仓库中的另一篇笔记 Redirect An Unauthorized User 展示了运行时、按业务逻辑触发的重定向:

  • Pages Router 时代,在getServerSideProps中做鉴权判断后返回redirect响应对象:
export async function getServerSideProps(context) { const session = await getServerAuthSession() const ability = getAbility({user: session?.user}) if (!ability.can('create', 'Post')) { return { redirect: { destination: '/posts', permanent: false, }, } } return { props: {}, } }
  • App Router 下则更简洁,直接在 Server Component 中调用next/navigation的redirect函数:
import { redirect } from 'next/navigation' export default async function CreatePost() { const session = await getServerAuthSession() const ability = getAbility({user: session?.user}) if (!ability.can('create', 'Post')) { redirect('/posts') } // JSX follows return (...) }

两类方案的分工建议:URL 本身发生了迁移、需要全站统一兜底 → 用next.config.js的redirects();跳转依赖登录态、权限等运行时数据 → 用getServerSideProps返回redirect或next/navigation的redirect()。把两者结合使用,才能覆盖完整的需求面。

本地开发时验证重定向是否生效

配置写好后,无需部署即可本地验证。启动开发服务器:

npm run dev # 等价于 next dev,默认监听 http://localhost:3000

然后在另一个终端用curl -I只看响应头,检查状态码与Location:

curl -I http://localhost:3000/blog/old-blog-post-name curl -I http://localhost:3000/store

预期输出分别类似:

HTTP/1.1 308 Permanent Redirect Location: /blog/new-blog-post-name
HTTP/1.1 308 Permanent Redirect Location: https://store.example.com

把规则的permanent改为false后重复上述请求,状态码会变为307 Temporary Redirect。生产构建(next build && next start)同样会应用这些规则,因此本地开发与线上行为完全一致,这正是本方案相对于vercel.json的核心价值。

仓库内延伸阅读

  • Define URL Redirects In The Next Config:本文的原始出处笔记;
  • Add Web Server Layer Redirects:vercel.json方案对照阅读;
  • Redirect An Unauthorized User:运行时重定向的两种写法;
  • README.md:TIL 仓库全量目录,可检索更多 Next.js 相关笔记。
  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载
上一篇:SkillSpector蓝队防御:AI Agent技能安全运营与事件响应完整指南
下一篇:IPTVnator:免费跨平台IPTV播放器完整指南,3步就能看起直播

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询