通过 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配置,统一管理跨域资源策略,使方案更完善。
通过中间件驱动的域名级路由治理,你就能用一套代码、一个部署,安全灵活地复用核心逻辑,同时满足不同品牌站点的业务隔离需求,既省心又省力。
