如何在Vercel上将多个Next.js页面动态绑定自定义域名
在Next.js + Vercel实现用户自定义域名绑定(类似Super.so)
核心思路
通过域名映射存储 + Vercel域名配置 + Next.js边缘中间件(Middleware) 实现动态路由与域名绑定,完成两类场景处理:
- 用户访问自定义域名(如
joshwebsite.io)时,渲染对应用户页面(/user/josh) - 用户访问原域名用户页(如
domainzzz.com/user/josh)时,自动重定向到其自定义域名(如果存在)
步骤1:存储域名-用户映射关系
需要持久化存储记录用户与绑定域名的对应关系,可选用数据库(PostgreSQL、MongoDB)或Vercel KV。示例数据结构:
| 用户名 | 自定义域名 | 状态 |
|---|---|---|
| josh | joshwebsite.io | 已启用 |
| bob | fannythebeauty.co | 已启用 |
| yann | null | 未绑定 |
用Prisma定义模型的示例(schema.prisma):
model User { id String @id @default(cuid()) username String @unique customDomain String? @unique // 存储自定义域名 // 其他用户字段... }
步骤2:在Vercel添加自定义域名
- 登录Vercel控制台进入目标项目
- 进入
Settings > Domains,点击Add,依次添加所有用户的自定义域名(如joshwebsite.io、fannythebeauty.co) - 指导用户完成DNS解析:
- 主域名(如
joshwebsite.io):添加A记录指向Vercel官方IP76.76.21.21 - 子域名:添加CNAME记录指向
cname.vercel-dns.com
- 主域名(如
- 等待Vercel完成域名所有权验证
步骤3:用Next.js Middleware处理路由与重定向
创建app/middleware.ts(App Router)或pages/_middleware.ts(Pages Router),实现核心逻辑:
逻辑1:自定义域名访问 → 映射到用户页面
当用户访问自定义域名时,查询数据库匹配对应用户,将请求转发到/user/[username]路由。
逻辑2:原域名用户页访问 → 重定向到自定义域名(如果存在)
当用户访问domainzzz.com/user/[username]时,查询该用户是否有绑定域名,若有则执行301永久重定向。
示例代码(App Router):
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' import { prisma } from '@/lib/prisma' // 替换为你的数据库实例 export async function middleware(request: NextRequest) { const host = request.headers.get('host')?.replace(':443', '') // 去除端口,获取纯域名 const pathname = request.nextUrl.pathname // 场景1:处理自定义域名访问 if (host && host !== 'domainzzz.com') { // 排除原域名 const user = await prisma.user.findUnique({ where: { customDomain: host } }) if (user) { // 转发请求到对应用户页面,保留原请求参数与方法 const newUrl = new URL(`/user/${user.username}`, request.url) return NextResponse.rewrite(newUrl) } else { // 无匹配用户的自定义域名,重定向到原域名首页 return NextResponse.redirect(new URL('/', request.url)) } } // 场景2:处理原域名下的用户页访问 const userMatch = pathname.match(/^\/user\/([a-z0-9-_]+)$/) if (userMatch) { const username = userMatch[1] const user = await prisma.user.findUnique({ where: { username } }) if (user?.customDomain) { return NextResponse.redirect(`https://${user.customDomain}`, { status: 301 }) } } // 其他请求正常放行 return NextResponse.next() } // 指定中间件生效范围,排除静态资源与API export const config = { matcher: [ '/((?!api|_next/static|_next/image|favicon.ico).*)', ], }
步骤4:优化与注意事项
- 边缘缓存:为减少数据库查询压力,可将域名-用户映射缓存到Vercel KV或Redis,利用边缘节点提升响应速度
- HTTPS自动配置:Vercel会自动为添加的域名申请Let's Encrypt SSL证书,无需手动配置
- 域名唯一性约束:数据库层面需为
customDomain字段添加唯一约束,避免多个用户绑定同一域名 - 本地测试:修改本地
hosts文件,将自定义域名指向127.0.0.1,即可在本地测试路由逻辑
内容的提问来源于stack exchange,提问作者Steffi
相关产品推荐
相关产品推荐

