
本文详解在 Next.js 中不依赖 window.location.href 或 React Router 获取当前 URL 的两种主流方法:服务端通过 getServerSideProps 上下文、客户端通过 useRouter,兼顾 SSR/SSG 兼容性与安全性。
本文详解在 next.js 中不依赖 `window.location.href` 或 react router 获取当前 url 的两种主流方法:服务端通过 `getserversideprops` 上下文、客户端通过 `userouter`,兼顾 ssr/ssg 兼容性与安全性。
在 Next.js 应用中,直接调用 window.location.href 会导致服务端渲染(SSR)报错(ReferenceError: window is not defined),而引入 React Router 则属于冗余依赖——Next.js 自带的路由系统已提供更原生、更可靠的 URL 访问能力。正确做法应根据执行环境(服务端 or 客户端)选择对应方案。
✅ 服务端获取 URL(推荐用于 SSR 场景)
在 getServerSideProps 中,可通过 context.req 安全访问原始 HTTP 请求信息。req.headers.host 给出域名(含端口),结合 req.url 可拼出完整 URL:
// pages/example.tsx
export const getServerSideProps = async (context) => {
const { req } = context;
const host = req.headers.host || 'localhost:3000';
const protocol = req.headers['x-forwarded-proto'] || 'http';
const url = `${protocol}://${host}${req.url}`;
return {
props: {
fullUrl: url,
hostname: host,
pathname: new URL(req.url, `https://${host}`).pathname,
},
};
};
export default function ExamplePage({ fullUrl, hostname, pathname }: {
fullUrl: string;
hostname: string;
pathname: string;
}) {
return (
<div>
<h2>服务端解析的 URL</h2>
<p><strong>完整地址:</strong>{fullUrl}</p>
<p><strong>主机名:</strong>{hostname}</p>
<p><strong>路径名:</strong>{pathname}</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8483" title="dmap-jsapi-skill"><img
src="https://img.php.cn/upload/skill/000/000/081/179206214475645.jpg" alt="dmap-jsapi-skill" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8483" title="dmap-jsapi-skill" class="overflowclass">dmap-jsapi-skill</a>
<p class="overflowclass">DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8483" title="dmap-jsapi-skill" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
</div>
);
}
⚠️ 注意事项:
- req.url 是相对路径(如 /blog/nextjs-ssr),需手动补全协议与 host 才构成绝对 URL;
- 若部署在反向代理后(如 Vercel、Nginx),优先读取 x-forwarded-proto 和 x-forwarded-host 头,避免协议误判;
- 此方式仅适用于页面级数据预取(getServerSideProps / getStaticProps),不适用于组件内部。
✅ 客户端获取 URL(推荐用于交互逻辑)
在组件中,应使用 Next.js 官方 useRouter Hook——它返回的 router 对象包含 pathname、query、asPath 等结构化字段,完全规避 window 依赖:
// components/UrlDisplay.tsx
'use client'; // 显式声明为 Client Component
import { useRouter } from 'next/router';
export default function UrlDisplay() {
const router = useRouter();
// asPath 包含完整路径 + 查询参数(如 /about?ref=home)
// pathname 仅返回路径部分(如 /about)
// query 是解析后的对象(如 { ref: 'home' })
return (
<div>
<h3>客户端路由状态</h3>
<ul>
<li>
<strong>当前路径:</strong>{router.asPath}</li>
<li>
<strong>纯路径名:</strong>{router.pathname}</li>
<li>
<strong>查询参数:</strong>{JSON.stringify(router.query)}</li>
</ul>
</div>
);
}
? 提示:
- router.asPath 最接近传统 window.location.href 的语义,但它是 Next.js 路由系统的“虚拟路径”,支持客户端导航(如 )而无需刷新;
- 若需监听 URL 变化,可结合 useEffect 与 router.events.on('routeChangeStart', ...);
- 切勿在服务端组件(Server Components)中调用 useRouter —— 会触发运行时错误。
? 总结:按需选择,避免陷阱
| 场景 | 推荐方式 | 关键优势 |
|---|---|---|
| 页面首次加载、SEO 友好、需服务端上下文(如鉴权、A/B 测试) | getServerSideProps + context.req | 安全、可靠、无 hydration 风险 |
| 客户端交互、动态更新、表单重定向、SPA 式体验 | useRouter Hook | 响应式、轻量、与 Next.js 路由深度集成 |
最后提醒:永远不要在服务端代码中引用 window 或 document;若需 URL 解析工具(如问题中提到的 url-parse),请确保其仅在客户端执行(例如包裹在 typeof window !== 'undefined' 条件中),或改用 Node.js 内置 URL 构造函数(如示例中所示),以保障跨环境兼容性。










