NextJS 11如何基于域名通过getServerSideProps渲染动态内容?
多租户域名下的Next.js国际化方案
针对你遇到的Next.js官方i18n配置无法支持多域名映射同一locale、且无法通过TLD区分内容的问题,以下是几种可行的替代方案:
1. 用Middleware全局处理域名->Locale映射
Next.js的Middleware可以在请求到达页面之前拦截处理,适合全局统一解析域名并设置Locale,比单独在每个页面的getServerSideProps里处理更高效。
示例代码(middleware.ts):
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; // 定义域名与locale的映射表 const DOMAIN_LOCALE_MAP = { 'stagingus.sitename.net': 'en-US', 'staginguk.sitename.net': 'en-GB', 'sitename.com': 'en-US', 'dev.sitename.com': 'en-US', }; export function middleware(request: NextRequest) { const host = request.headers.get('host'); const locale = DOMAIN_LOCALE_MAP[host as keyof typeof DOMAIN_LOCALE_MAP] || 'en-US'; // 将locale存入请求头,方便后续页面获取 const requestHeaders = new Headers(request.headers); requestHeaders.set('x-locale', locale); // 也可以设置cookie,让客户端也能获取到locale const response = NextResponse.next({ request: { headers: requestHeaders }, }); response.cookies.set('locale', locale); return response; } // 指定需要拦截的路由(这里匹配所有路由) export const config = { matcher: '/:path*', };
之后在页面组件或getServerSideProps中,就可以通过req.headers.get('x-locale')或者cookie获取当前locale,再加载对应内容。
2. 集中式域名配置映射表
如果不想用Middleware,可以在项目中维护一个集中的域名-locale配置文件,在getServerSideProps或getInitialProps中统一匹配,避免每个页面重复写正则。
示例代码(config/domain-locale.ts):
export const domainLocaleMap = new Map<string | RegExp, string>([ ['stagingus.sitename.net', 'en-US'], ['staginguk.sitename.net', 'en-GB'], ['sitename.com', 'en-US'], ['dev.sitename.com', 'en-US'], // 支持通配符匹配,比如所有us开头的staging域名 [/^stagingus\..+\.net$/, 'en-US'], [/^staginguk\..+\.net$/, 'en-GB'], ]); export function getLocaleFromHost(host: string): string { for (const [key, locale] of domainLocaleMap) { if (typeof key === 'string') { if (host === key) return locale; } else if (key.test(host)) { return locale; } } return 'en-US'; // 默认locale }
在页面的getServerSideProps中使用:
import { getLocaleFromHost } from '../config/domain-locale'; export async function getServerSideProps(ctx) { const host = ctx.req.headers.host; const locale = getLocaleFromHost(host); // 根据locale获取对应内容 const content = await fetchContentByLocale(locale); return { props: { locale, content } }; }
3. 自定义i18n逻辑(脱离官方i18n配置)
放弃Next.js官方的i18n配置,直接用react-i18next等第三方国际化库,完全通过域名控制语言切换,灵活性更高。
步骤:
- 安装依赖:
npm install react-i18next i18next - 初始化i18n(
i18n.ts):
import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; // 导入语言包 import enUS from './locales/en-US.json'; import enGB from './locales/en-GB.json'; const resources = { 'en-US': { translation: enUS }, 'en-GB': { translation: enGB }, }; i18n.use(initReactI18next).init({ resources, fallbackLng: 'en-US', interpolation: { escapeValue: false }, }); export default i18n;
- 在
_app.tsx中根据域名切换语言:
import { useEffect } from 'react'; import i18n from '../i18n'; import { getLocaleFromHost } from '../config/domain-locale'; function MyApp({ Component, pageProps, locale }) { useEffect(() => { i18n.changeLanguage(locale); }, [locale]); return <Component {...pageProps} />; } MyApp.getInitialProps = async (appContext) => { const host = appContext.ctx.req.headers.host; const locale = getLocaleFromHost(host); const appProps = await typeof App !== 'undefined' ? App.getInitialProps(appContext) : {}; return { ...appProps, locale }; }; export default MyApp;
4. 结合多租户数据模型
如果你的多租户场景中,每个域名对应一个租户实例,可以在数据库中存储租户与locale的关联关系,通过域名查询租户信息后获取对应的locale。这种方式适合租户数量多、需要动态配置的场景。
示例代码(getServerSideProps中):
export async function getServerSideProps(ctx) { const host = ctx.req.headers.host; // 从数据库查询租户信息 const tenant = await db.tenant.findOne({ where: { domain: host } }); const locale = tenant?.locale || 'en-US'; // 获取对应内容 const content = await fetchContentByTenant(tenant.id); return { props: { locale, content, tenant } }; }
内容的提问来源于stack exchange,提问作者mcclosa
相关产品推荐
相关产品推荐

