You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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。示例数据结构:

用户名自定义域名状态
joshjoshwebsite.io已启用
bobfannythebeauty.co已启用
yannnull未绑定

用Prisma定义模型的示例(schema.prisma):

model User {
  id           String   @id @default(cuid())
  username     String   @unique
  customDomain String?  @unique // 存储自定义域名
  // 其他用户字段...
}

步骤2:在Vercel添加自定义域名

  1. 登录Vercel控制台进入目标项目
  2. 进入Settings > Domains,点击Add,依次添加所有用户的自定义域名(如joshwebsite.io、fannythebeauty.co)
  3. 指导用户完成DNS解析:
    • 主域名(如joshwebsite.io):添加A记录指向Vercel官方IP 76.76.21.21
    • 子域名:添加CNAME记录指向cname.vercel-dns.com
  4. 等待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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:33:35