求助:NextJS项目中如何在_document.js文件获取hostname?
在NextJS的_document.js中获取Hostname的解决方案
如果你的_document.js里getInitialProps的context.req是undefined,通常是因为代码在客户端执行了(比如客户端导航跳转)。以下是几种靠谱的解决方法:
1. 区分服务端/客户端环境动态获取
直接通过环境判断分别处理服务端和客户端的hostname获取逻辑,覆盖所有场景:
import Document, { Html, Head, Main, NextScript } from 'next/document' class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx) let hostname = '' // 服务端:从请求头取,优先处理反向代理场景 if (ctx.req) { hostname = ctx.req.headers['x-forwarded-host'] || ctx.req.headers.host } // 客户端:直接访问window对象 else { hostname = window.location.hostname } return { ...initialProps, hostname } } render() { return ( <Html> <Head> {/* 示例:用hostname设置站点元信息 */} <meta property="og:site_name" content={this.props.hostname} /> </Head> <body> <Main /> <NextScript /> </body> </Html> ) } } export default MyDocument
2. 用环境变量固定配置(适合域名不变的场景)
如果你的项目域名是固定的(比如开发环境localhost:3000,生产环境your-domain.com),直接在.env文件里配置全局变量:
# .env.local(开发环境) NEXT_PUBLIC_HOSTNAME=localhost:3000 # .env.production(生产环境) NEXT_PUBLIC_HOSTNAME=your-domain.com
然后在_document.js里直接引用:
const hostname = process.env.NEXT_PUBLIC_HOSTNAME
这种方法最简单,不需要处理环境判断,适合域名固定的项目。
3. 针对App Router的替代方案(NextJS 13+)
如果你用的是App Router(取代了Pages Router的_document.js),在app/layout.js里可以这样获取:
import { headers } from 'next/headers' export default function RootLayout({ children }) { let hostname = '' // 服务端:通过headers()获取 try { hostname = headers().get('x-forwarded-host') || headers().get('host') } catch (e) { // 客户端:捕获服务端API调用错误,改用window hostname = window.location.hostname } return ( <html lang="en"> <head> <meta property="og:site_name" content={hostname} /> </head> <body>{children}</body> </html> ) }
关键注意点
- 反向代理场景(比如用Nginx、Vercel部署)下,必须优先用
x-forwarded-host请求头,否则拿到的可能是代理服务器的域名,不是用户实际访问的地址。 _document.js仅在Pages Router中生效,App Router请用layout.js替代。
内容的提问来源于stack exchange,提问作者Milan Patel
相关产品推荐
相关产品推荐

