如何在集成Clerk Auth的NextJS 14中使用动态子域名
解决Next.js 14 App Router中Clerk Auth与动态子域名共存的问题
要同时实现Clerk认证和动态子域名路由,你需要自定义中间件函数,将子域名处理逻辑与Clerk的中间件逻辑结合,而不是直接导出Clerk的默认中间件。以下是具体实现步骤:
1. 修改根目录的middleware.ts
替换原代码为以下内容,我们会先解析子域名并重写路径,再交由Clerk处理认证:
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server"; import { NextResponse, type NextRequest } from "next/server"; // 定义需要跳过子域名处理的路径(比如Clerk的认证路由) const isClerkRoute = createRouteMatcher([ "/sign-in(.*)", "/sign-up(.*)", "/clerk(.*)", ]); export default async function middleware(request: NextRequest) { // 1. 处理动态子域名 const host = request.headers.get("host"); if (!host) return NextResponse.next(); // 配置你的主域名(生产环境)和本地开发域名 const mainDomain = "mysite.app"; const localDomain = "localhost:3000"; let subdomain: string | null = null; // 解析子域名 if (host.includes(mainDomain)) { subdomain = host.split(".")[0]; // 排除主域名本身(比如mysite.app) if (subdomain === mainDomain.split(".")[0]) subdomain = null; } else if (host.includes(localDomain)) { // 本地开发环境,比如thomas-bistro.localhost:3000 subdomain = host.split(".")[0]; } // 如果存在有效子域名,重写路径为动态路由格式 if (subdomain && !isClerkRoute(request)) { // 重写路径:将 /xxx 转为 /org/[subdomain]/xxx const newUrl = new URL(`/org/${subdomain}${request.nextUrl.pathname}`, request.url); // 保留原查询参数 newUrl.search = request.nextUrl.search; request.nextUrl.pathname = newUrl.pathname; } // 2. 调用Clerk中间件处理认证 const clerkResponse = await clerkMiddleware()(request); return clerkResponse; } export const config = { matcher: [ // 保持原有的匹配规则,确保覆盖所有需要处理的路径 '/((?!_next|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', '/(api|trpc)(.*)', ], };
2. 配置App Router的动态路由
在app目录下创建对应的动态路由结构,比如:
app/ org/ [orgId]/ page.tsx // 子域名对应的主页 layout.tsx // 子域名的布局 // 其他页面组件... // 原有的根路由组件...
这样,当用户访问thomas-bistro.mysite.app时,中间件会将路径重写为/org/thomas-bistro,自动匹配到app/org/[orgId]/page.tsx,你可以在组件中通过params.orgId获取子域名:
// app/org/[orgId]/page.tsx export default function OrgPage({ params }: { params: { orgId: string } }) { return <div>欢迎访问 {params.orgId} 的专属页面</div>; }
3. Clerk配置注意事项
- 登录Clerk Dashboard,在Settings > Domain中,将你的主域名(比如
mysite.app)添加为允许的域名,并勾选"Allow subdomains"选项,确保Clerk在子域名下能正常处理认证。 - 本地开发时,你需要修改
hosts文件(Windows:C:\Windows\System32\drivers\etc\hosts,Mac/Linux:/etc/hosts),添加子域名映射:
这样就能在本地访问127.0.0.1 thomas-bistro.localhostthomas-bistro.localhost:3000测试子域名功能。
常见问题排查
- 如果你之前出现"无middleware导出"错误,是因为你没有正确导出自定义的async函数,确保
export default async function middleware(request: NextRequest)的写法正确。 - 子域名解析失败:检查
mainDomain和localDomain是否与你的实际域名匹配,注意不要包含协议(http/https)。 - Clerk认证失效:确保Clerk的instance domain配置正确,且子域名在允许列表中。
内容的提问来源于stack exchange,提问作者Thomas Price
相关产品推荐
相关产品推荐

