Next.js多域名页面路由差异化实现
作者:技术拾光时间:2026-07-12 08:21:00浏览:254
通过Next.js中间件获取请求域名,结合Host头动态控制路由可见性,可实现同一套代码在多个域名下展示差异化页面,如仅主域名显示/about,其他域名重定向或隐藏,有效支持多品牌站点场景。
通过 Next.js 中间件(Middleware)根据请求的 Host 头动态控制页面可见性,可实现同一应用在多个域名下展示不同路由(如仅在 something.com 显示 /about,而在 somethingelse.com 中隐藏或重定向)。
在同一个 Next.js 应用中,仅需部署一套代码,即可实现在不同域名下展示不同路由。例如,主站 something.com 需要完整的 /about 页面,而落地页 somethingelse.com 只保留首页和登录,将 /about 隐藏。这种需求在 SaaS 多品牌或多站点场景中十分常见,而 Next.js 中间件正是解决这一问题的有效工具。
在 Next.js 13+(App Router)中,中间件运行在请求到达服务端组件之前,是一个轻量级的路由拦截层。通过中间件,可以获取请求的域名和路径,然后决定是放行、重定向还是直接返回 404。这样一来,一套代码能够同时服务多个域名,主站和落地页各取所需,核心逻辑(如登录态、API 调用等)得以复用,无需维护多套代码或部署多个实例。
实现原理:基于 Host 的条件路由控制
中间件运行在边缘环境(Edge Runtime),通过 request.headers.get('host') 获取当前请求的域名,再结合 request.nextUrl.pathname 判断路径,从而实现差异化的路由决策。
以下是一个生产环境可直接使用的示例:
// src/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const host = request.headers.get('host').toLowerCase() || '';
const pathname = request.nextUrl.pathname;
// 定义域名白名单策略
const isMainDomain = host === 'something.com' || host.endsWith('.something.com');
const isLandingDomain = host === 'somethingelse.com' || host.endsWith('.somethingelse.com');
// /about 仅对主域名开放,其他域名重定向至首页
if (pathname.startsWith('/about')) {
if (!isMainDomain) {
return NextResponse.redirect(new URL('/', request.url));
}
}
// 可扩展:/admin 仅限内部域名访问
if (pathname.startsWith('/admin') && !host.includes('internal.')) {
return NextResponse.rewrite(new URL('/404', request.url));
}
// 允许所有其他请求继续
return NextResponse.next();
}
// 指定中间件生效路径(支持 glob 匹配)
export const config = {
matcher: [
'/about/:path*',
'/admin/:path*',
// 注意:若需拦截根路径或动态路由,也应显式列出
],
};
关键注意事项
- matcher 必须显式声明:中间件不会自动匹配所有路径,只有列在 matcher 里的路径才会触发这段逻辑。根路径或动态路由若需拦截,请务必添加。
- Host 头校验要细致:避免仅写
host === 'somethingelse.com',否则可能遗漏子域名(如xxx.somethingelse.com)。建议使用endsWith()或正则,同时将 host 转为小写再比较,以防大小写问题。 - 小心循环重定向:重定向的目标路径(如
/)不应出现在 matcher 列表中,否则会无限跳转。可在逻辑中加判断排除。 - 静态生成(SSG)页面不受中间件影响:中间件仅对服务端渲染(SSR)或动态路由的请求生效。若某个页面(如
app/about/page.tsx)被预渲染为静态 HTML,它会直接走 CDN 缓存,中间件无法触及。因此,若希望路由始终走服务端渲染,需配合generateStaticParams: false或dynamic = 'force-dynamic'。 - NX 单体仓库里的位置:若项目为 NX monorepo,请确保
middleware.ts放在 Next.js 应用的src/根目录下,而非 workspace 根目录。同时检查构建配置是否正确识别了中间件入口。
进阶建议
- 若权限控制更复杂(如需同时考虑域名和用户角色),可在中间件中调用 auth 服务验证会话,再做决策。
- 对于 SEO 敏感的页面(如 /about),建议对非授权域名返回 404(使用
NextResponse.next()配合自定义notFound()),而非重定向到首页,这样搜索引擎不会索引到错误路径。 - 结合
next.config.js中的images.domains和headers配置,统一管理跨域资源策略,获得更全面的控制。
通过中间件驱动的域名级路由治理,可以用一套代码、一个部署,安全灵活地复用核心逻辑,同时满足不同品牌站点的业务隔离需求,省心又省力。
