React-router带参数路由手动输入URL/刷新后资源加载异常问题
问题诱因
你遇到的问题本质是BrowserRouter模式下的单页应用路由与静态资源引用路径不匹配导致的,具体原因如下:
- 你使用的
BrowserRouter依赖HTML5 History API实现前端路由,页面内点击Link跳转时,仅在前端修改路由状态、不会真实向服务器发起资源请求,所以表现正常。但刷新页面/新标签打开链接时,浏览器会直接向服务器请求当前URL路径对应的资源,而单页应用只有根路径的index.html是真实存在的,服务器不存在/appointments、/signin这类路径对应的静态资源。 - 你的静态资源(样式表、图片等)用的是相对路径引用,当你在二级及以上路径刷新时,浏览器会以当前路径为基准拼接资源地址,比如你在
https://yourdomain.com/appointments页面刷新,浏览器会请求https://yourdomain.com/appointments/css/xxx.css、https://yourdomain.com/appointments/images/xxx.png这类不存在的资源,自然就会出现样式错乱、图片丢失的问题。 - 补充你代码里的两处逻辑错误:
useHistory必须在BrowserRouter包裹的组件内部调用,你当前的App组件本身没有被BrowserRouter包裹(你是在App的返回值里才写的BrowserRouter),这里的useHistory调用会抛出异常。- 代码末尾的
BrowserRouter闭合标签写错了,应该是</BrowserRouter>而不是<BrowserRouter>。
解决办法
- 先修复代码错误
- 将
BrowserRouter移到App组件外层,比如在index.js中用BrowserRouter包裹<App />,确保App内部的路由钩子可以正常调用。 - 修正
BrowserRouter的闭合标签语法错误。
- 将
- 修正静态资源路径
- 将项目内所有样式、图片等静态资源的引用路径改为绝对路径(以
/开头),比如原来的./images/logo.png改为/images/logo.png。 - 如果是Create React App创建的项目,在
package.json中添加配置"homepage": "/",确保构建后的资源引用路径统一为根路径。
- 将项目内所有样式、图片等静态资源的引用路径改为绝对路径(以
- 配置服务器路由回退
所有场景下只要请求的资源不存在,都返回根目录的index.html,交由前端路由处理页面渲染:- 开发环境下如果用webpack-dev-server,在配置中添加
historyApiFallback: true即可。 - 生产环境用Nginx的话,在站点配置中添加
try_files $uri $uri/ /index.html;。
- 开发环境下如果用webpack-dev-server,在配置中添加
- 临时替代方案
如果暂时不想配置服务器规则,可以用HashRouter替代BrowserRouter,它基于URL的hash段实现路由,hash段不会发送到服务器,刷新时始终请求根路径的index.html,不会出现资源加载问题,缺点是URL中会多出#符号。
内容的提问来源于stack exchange,提问作者Vhintage
相关产品推荐
相关产品推荐

