Next.js多域名同URL路由配置:不同域名对应不同页面
解决Next.js多域名路由与公共页面布局适配问题
你的核心问题在于原自定义服务器的逻辑会将对应域名下的所有请求直接转发到/abc或/xyz根路径,导致/contact这类公共页面也被错误路由,无法正常访问。下面提供两种符合Next.js最佳实践的解决方案:
方案一:使用Next.js Middleware(推荐)
Next.js 12+内置的Middleware可以在请求到达页面之前处理路由重写,无需自定义服务器,更适配App Router架构。
步骤1:创建Middleware文件
在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') const pathname = request.nextUrl.pathname // 针对abc.com的路由规则 if (host === 'abc.com') { switch(pathname) { case '/home': return NextResponse.rewrite(new URL('/abc/home', request.url)) case '/contact': return NextResponse.rewrite(new URL('/abc/contact', request.url)) } } // 针对xyz.com的路由规则 else if (host === 'xyz.com') { switch(pathname) { case '/home': return NextResponse.rewrite(new URL('/xyz/home', request.url)) case '/contact': return NextResponse.rewrite(new URL('/xyz/contact', request.url)) } } return NextResponse.next() } // 指定仅对/home和/contact路径应用中间件 export const config = { matcher: ['/home', '/contact'], }
步骤2:调整项目结构与组件复用
- 新建公共Contact组件:
src/app/components/Contact.tsx
export default function Contact() { return ( <div> <h1>联系我们</h1> <p>这是所有域名共享的联系页面内容</p> </div> ) }
- 在
abc和xyz目录下分别创建contact页面,复用公共组件:
src/app/abc/contact/page.tsx
import Contact from '../../components/Contact' export default function ABCContact() { return <Contact /> }
src/app/xyz/contact/page.tsx
import Contact from '../../components/Contact' export default function XYZContact() { return <Contact /> }
方案二:修改自定义Server逻辑
如果必须保留自定义服务器,需要调整路由判断逻辑,仅针对特定路径转发:
const { createServer } = require('http') const { parse } = require('url') const next = require('next') const dev = process.env.NODE_ENV !== 'production' const hostname = 'localhost' const port = 3000 const app = next({ dev, hostname, port }) const handle = app.getRequestHandler() app.prepare().then(() => { createServer(async (req, res) => { try { const parsedUrl = parse(req.url, true) const { pathname } = parsedUrl const host = req.headers.host; if (host === 'abc.com') { switch(pathname) { case '/home': await app.render(req, res, '/abc/home', parsedUrl.query) break case '/contact': await app.render(req, res, '/abc/contact', parsedUrl.query) break default: await handle(req, res) } } else if (host === 'xyz.com') { switch(pathname) { case '/home': await app.render(req, res, '/xyz/home', parsedUrl.query) break case '/contact': await app.render(req, res, '/xyz/contact', parsedUrl.query) break default: await handle(req, res) } } else { await handle(req, res) } } catch (err) { console.error('Error occurred handling', req.url, err) res.statusCode = 500 res.end('internal server error') } }) .once('error', (err) => { console.error(err) process.exit(1) }) .listen(port, () => { console.log(`> Ready on http://${hostname}:${port}`) }) })
本地测试配置
修改本地hosts文件,将测试域名指向localhost:
127.0.0.1 abc.com 127.0.0.1 xyz.com
此时访问abc.com:3000/home会加载/abc/home页面,abc.com:3000/contact会加载复用公共组件的/abc/contact页面并自动应用abc的布局;xyz域名同理。
内容的提问来源于stack exchange,提问作者Arjun
相关产品推荐
相关产品推荐

