- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
本篇整理 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.json | next.config.js的redirects() |
|---|---|---|
| 生效层级 | Vercel 平台 Web Server 层 | Next.js 应用层(dev server / 构建产物) |
本地next dev是否生效 | 否 | 是 |
| 状态码控制 | 默认 308 | 通过permanent显式控制 308 / 307 |
| 配置格式 | JSON | JavaScript(支持逻辑与动态生成) |
| 与框架耦合度 | 依赖 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-nameHTTP/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
相关推荐
微信聊天记录如何免费导出成文档并生成年度报告:WeChatMsg 新手完整指南
微信聊天记录如何免费导出成文档并生成年度报告:WeChatMsg 新手完整指南 换了新手机,把用了好几年的微信聊天记录往新设备上一迁,中途断了一次,几百条消息说
Read the Docs 自定义 URL 重定向(Redirects)配置实战指南
Read the Docs 自定义 URL 重定向(Redirects)配置实战指南 本篇指南讲解如何在 Read the Docs 项目中配置用户自定义重定向
后端文档redirect-with-fallback 示例深度解析:Next.js Route Handler 与 next.config.js redirects 双轨重定向方案
redirect with fallback 示例深度解析:Next.js Route Handler 与 next.config.js redirects 双
示例工程前端后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考