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 配置,统一管理跨域资源策略,获得更全面的控制。

通过中间件驱动的域名级路由治理,可以用一套代码、一个部署,安全灵活地复用核心逻辑,同时满足不同品牌站点的业务隔离需求,省心又省力。