问题描述
使用BrowserRouter
建立路由,开发过程中没有问题,但是build后放到tomcat中导致白屏,没有渲染组件,也没有404。
如果使用HashRouter
的话没有问题,但是强迫症表示不好看。。。
环境:
- 使用
create-react-app
脚手架搭建的react环境 - 后台使用spring-boot
问题原因
首先分析下出现此问题的原因: 在React项目中我们经常需要采用React-Router来配置我们的页面路由,React-Router 是建立在 history 之上的,常见的history路由方案有三种形式,分别是:
- hashHistory
hashHistory 使用 URL 中的 hash(#)部分去创建路由,举例来说,用户访问http://www.example.com/,实际会看到的是http://www.example.com/#/。
- browserHistory
browserHistory 是使用 React-Router 的应用推荐的 history方案。它使用浏览器中的 History API 用于处理 URL,创建一个像example.com/list/123这样真实的 URL 。
- createMemoryHistory
Memory history 不会在地址栏被操作或读取。这就解释了我们是如何实现服务器渲染的。同时它也非常适合测试和其他的渲染环境(像 React Native )。和另外两种history的一点不同是你必须创建它,这种方式便于测试。
在browserHistory 模式下,URL 是指向真实 URL 的资源路径,当通过真实 URL 访问网站的时候,由于路径是指向服务器的真实路径,但该路径下并没有相关资源,或者后端没有处理对应的路由的接口,所以用户访问的资源不存在。
本地开发时,使用browserHistory是没有问题的,这是因为webpack.config.js中使用 webpack-dev-server 已经做了配置。
webpackConfig.devServer = {
contentBase: path.resolve(__dirname, 'build'),
compress: true, //gzip压缩
historyApiFallback: true,
};
解决方法
在实验室师兄的帮助下,选择使用nginx
,前后端分离部署来解决(之前是将前端build之后的文件放到spring-boot中然后丢到tomcat中)。
-
将
npm run build
之后的文件夹丢到nginx的html文件夹下(也可以单独再创建一个文件夹来存放,但是要在conf文件里面配置root) -
将后端的代码打包后丢到tomcat中
-
更改
nginx.conf
文件,将请求都转到index.html,让React-Router
去匹配路由然后渲染组件location / { root html; index index.html index.htm; #将请求都转到index.html,避免刷新,出现404,这是解决的重点 try_files $uri $uri/ /index.html; } #因为我的后端请求都是由_api开头的,所有如果请求是此模式,将其转发到后台端口 location ^~ /_api { index index.html index.html; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:8081/bike; #路由跳转,这里写tomcat端口和路由 rewrite ^/_api/(.*)$ /$1 break; }
再次遇到问题
根据上述部署完毕后,首页刷新和跳转没有问题,不在白屏或者404。但是二级路径及子路由出现白屏和静态资源找不到等问题。
原因
之前将build文件丢到tomcat中时曾经出现过找不到静态资源问题,是因为react build后的寻找静态资源是在根目录下的static文件夹,放到tomcat中不在根目录,需要改成相对路径,比如更改react-scripts/config/paths.js
文件或者package.json
文件:
-
更改
react-scripts/config/paths.js
文件将
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
改为envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : './');
-
更改
package.json
文件添加
homepage:".",
但是部署到nginx中后,因为配置了root,所以寻找相对路径找不到文件,需要寻找绝对路径。
解决方法
将上述nginx操作的root复原即可。
参考资料:
react router BrowserRoute部署后页面空白问题