哈希路由是兼容老环境的权宜之计,现代项目应优先使用 createBrowserRouter;其URL中#源于浏览器片段标识符机制,不触发请求但影响SEO与API使用;迁移需替换路由创建方式并配置服务端fallback。

哈希(#)本身不是问题,而是前端路由在不支持 History API 的老环境或特定部署场景下的权宜之计;现代项目应优先用 createBrowserRouter(React Router v6.4+)或 history.pushState,仅当必须兼容 IE11、静态托管无服务端重写时,才保留哈希路由。
哈希路由为什么会在 URL 里多出 #
这是浏览器原生行为:所有以 # 开头的片段标识符(fragment identifier)不会触发页面刷新,也不发请求给服务端。前端路由库(如早期 React Router v3、Vue Router 的 mode: 'hash')正是靠监听 hashchange 事件来驱动视图切换。
- 服务端完全看不到
#及其后内容,所以部署到 Nginx/Apache 时无需配置重写规则 - 但分享链接
https://site.com/#/user/123看起来不专业,SEO 友好性差,且无法使用scrollRestoration等新 API - 部分分析工具(如 Google Analytics)默认忽略哈希变化,需手动打点
怎么把哈希路由换成 History 路由(React Router v6.4+)
核心是替换路由创建方式,并确保服务端能 fallback 到 index.html。不改代码只换部署配置,必然 404。
- 把
createHashRouter换成createBrowserRouter - 移除所有
basename中硬编码的/#或类似逻辑 - Nginx 配置加一条
try_files $uri $uri/ /index.html;,Apache 加.htaccess重写规则 - 若部署在 GitHub Pages 或 Netlify,需分别启用
404.htmlfallback 或设置_redirects文件
示例迁移:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
// 迁移前(哈希)
const router = createHashRouter(routes);
// 迁移后(History)
const router = createBrowserRouter(routes, {
basename: "/app", // 可选,对应子路径部署
});
必须用哈希时,怎么避免常见坑
不是所有场景都能立刻切 History —— 比如内网系统要求兼容 IE11,或嵌入三方平台被限制修改服务端配置。这时得管好哈希本身。
- 不要手动拼接
window.location.hash = "#/user?id=1",改用路由库的导航方法(如navigate("/user", { state: { id: 1 } })),否则丢失状态和 scroll behavior - 哈希参数含特殊字符(空格、中文、
&)必须encodeURIComponent,否则location.hash解析错乱 -
useLocation().hash在 React Router 中返回的是带#的完整字符串,提取路径要用location.hash.slice(1)或正则 - 服务端日志或埋点中若记录
document.referrer,注意它不含哈希,可能掩盖真实来源
哈希本身很简单,难的是判断「此刻是否真需要它」—— 很多团队保留哈希只是因为没验证过服务端 fallback 是否生效,或者误以为 CDN 不支持重写。上线前用 curl 测试 404 路径,比写十行哈希处理逻辑更重要。


















