碰到的问题
最近将项react项目打包成app的时候,或者说先经历一个npm run build命令打包后,发现将打包后的index.html打开一片空白!!Σ(っ °Д °;)っ我打开浏览器开发工具检查页面元素情况,发现APP组件已经挂载到页面最外层div上了,但是APP组件里什么也没有。我在想,APP组件里放的其实都是路由组件,这就说明了路由组件出问题了,没有被渲染出来。
我刚好百度搜 “为何打包react项目后,打开打包好的页面,是一片空白?” 时看见一个解决方案:将BrowserRouter改为HashRouter。我试着修改并重新打包,页面立马就出来了!不过,这两个路由有什么具体区别我是不太了解的,为什么可以这样修改,可以好好总结一下。
前端路由
首先,为什么需要前端路由这个东西?React是帮助我们开发单页面应用程序的一个框架,其中包含一个index.html文件,每个React Js组件在div元素都在这一个index.html文件中呈现就好了。
从用户角度看,不同URL对应不同的展示页面;对于我们编程开发的,路由就是URL和对应的处理函数的关系。以前,不同的URL与页面的映射,是服务器返回的,现在在前端就可以完成,且只需要一开始请求一次html就好了,后面切换URL的时候就改变部分需要改变的内容即可。(不过有个缺点,就是页面跳转时,你没法儿记住它之前的页面滚动位置库😫,每次都回到顶部)。
“Browser Router” or “Hash Router”
React实现路由功能可以用 “Browser Router” or “Hash Router”。
A that uses the HTML5 history API (
pushState
,replaceState
and thepopstate
event) to keep your UI in sync with the URL.A that uses the hash portion of the URL (i.e.
window.location.hash
) to keep your UI in sync with the URL.
他俩最直观的区别就是页面地址栏显示的url效果不同,你可以看见一个“#”被附加在HashRouter的URL的结尾处。
图:BroswerRouter 和 HashRouter
第二个应用区别是,如果你将React js编写的应用程序部署到生产服务器后,在生产环境中从一个组件切换到另一个组件。对于BrowserRouter,它使用浏览器中的 History API 处理 URL,它显示的URL 是指向真实 URL 的资源路径。比如说我们从“https://www.qqiuklele.cn/”到“https://www.qqiuklele.cn/blog”,服务器可能去搜索包含HTML文件的blog文件夹了,但并没有对应物理路径/文件,那么服务器可能会抛出一个错误“404:Page Not Found.”。这也是我们看到空白页面的原因。为了表明我们的整个应用程序是在单一页index.html中呈现的,可以使用HashRouter,在主域的末尾附加了“#”,就相当于告诉服务器,HTML代码将在index.html文件中加载。而且这些“#”是不会发送给服务器的,只是起到告知的作用。
解决方式
①改为HashRouter立马见效,但是看文档知道,官方推荐使用BrowserRouter,由于HashRouter没有使用html5中的history API,HashRouter不支持location.key和location.state。
state是router传值的其中一种方式,通过state的方式传值给下一个页面的时候,当到达新的页面,刷新或者后退之后再前进,BrowseRouter传递的值依然可以得到。所以需要知晓如何不影响BrowseRouter的使用。
②采用服务端支持,如nginx,指定目的文件夹和index.html后,也可以用BrowserRouter,这也是我之前使用BroswerRouter并部署到服务器后没有遇到空白页的情况。
server {
server_name react.com;
listen 80;
root /user/src/blog/dist;
index index.html;
location / {
try_files $uri /index.html;
}
}
③除此之外还有:通过修改webpack-dev-server运行方式、Node服务端配置(express或者koa)
详情参考:《React-Router browserHistory浏览器刷新出现页面404解决方案》
其本质的原理就是利用服务端将任何请求都指向
index.html
,而在React应用中index.html又刚好通过React-Router配置了相应的路由,我们让服务器返回index.html,后面就交给前端路由来实现无刷新加载对应页面。
更多参考文章:
个人博客同步:https://qqiuklele.cn/?p=216