问题始于一个项目中将前端和后端整合时发现的一个bug:这个项目所有页面的路由都是由前端代码完成的(react-router),而后端代码则是用Flask写的,且后端只在根路径(http://localhost:5000/
)渲染了前端的代码,此为前提。当用户从根路径打开页面时,一切正常。但当用户跳过根路径,而直接在浏览器中输入一个子路径时(比如http://localhost:5000/about
)出了问题,返回了404。并且用户在任意一个子路径进行刷新页面的操作时,也会返回404。
Client side routing VS. server side routing
The first big thing to understand about this is that there are now 2 places where the URL is interpreted, whereas there used to be only 1 in ‘the old days’. In the past, when life was simple, some user sent a request for http://example.com/about
to the server, which inspected the path part of the URL, determined the user was requesting the about page and then sent back that page.
With client-side routing, which is what React-Router provides, things are less simple. At first, the client does not have any JS code loaded yet. So the very first request will always be to the server. That will then return a page that contains the needed script tags to load React and React Router etc. Only when those scripts have loaded does phase 2 start. In phase 2, when the user clicks on the ‘About us’ navigation link for example, the URL is changed locally only to http://example.com/about
(made possible by the History API), but no request to the server is made. Instead, React Router does it’s thing on the client side, determines which React view to render and renders it. Assuming your about page does not need to make any REST calls, it’s done already. You have transitioned from Home to About Us without any server request having fired.
简单地说,client side routing就是通过前端代码的一顿操作,将本该由server端处理的工作给拦截了,并且自己给做了。为什么会有这种需求呢,其实熟悉一些前端就很好理解了:交给server端处理,大部分情况就是重新渲染另一个页面,一般都伴随着页面的刷新,而对于前端代码而言,刷新页面就如同运行后端代码时重启系统,所有内存中存储的东西都没了,前端上很多复杂的操作也就很难实现了。为了能将“命运”掌握在自己手里,client side routing的技术也就应运而生。