我做了个实验,用 react + react-router + webpack 写了个SPA,包含一个 index
页面和一个about
页面
用
webpack-dev-server
启动,本地访问 http://localhost:3000/about 是可以直接访问的如果我把编译好的
index.html
和bundle.js
放到 Apache HTTP Server上,再直接访问 http:://localhost:3000/about 就访问不了了,但是先访问 http://localhost:3000/ ,在点击about
菜单是可以到达 http:://localhost:3000/about 的
这个实验是否说明了,react-router 只是客户端路由,并不是服务端路由?那意味着,如果我把 index.html
和 bundle.js
都放到CDN上的话,让域名指向CDN, 于是只能先访问根域名 http:://www.example.com/ 再点击 about 菜单,而无法直接访问 http://www.example.com/about 的,对吧?
感谢 @vimac 的回答,我总结一下答案:
createHashHistory
,createBrowserHistory
,createMemoryHistory
这三种方案,常见的是第一种,纯粹是客户端路由,第二种最现代化,客户端和服务端的URL完全一致,但是在代码方面需要多点代码处理服务端路由。我提这个问题的意图,原本是想把我的
index.html
和bundle.js
都放到CDN上,这样省钱,速度也快,不过这个部署方式,有个缺点,就是只能访问根域名 www.example.com, www.example.com/about 访问不了,会报出404错误,因为CDN不知道如何响应 www.example.com/about 这样的request所以,如果你写的是一个SPA, 故名思议,只有一个页面,即只有一个入口,只允许用户用唯一的入口来访问,这时候你可以把
index.html
和bundle.js
放到CDN上,然后把你的域名 www.example.com 指向CDN, 然后用户可以访问根域名来使用你的SPA, 然后用客户端路由浏览到www.example.com/about。 用户如果直接访问 www.example.com/about或者在浏览器里refresh, 都会404如果你写的是一个SPA,但是你希望用户能够直接访问 www.example.com/about,那么你必须要启用服务端路由,即这时候你得改写你的代码,让 react-router 在服务端也运行起来,例如新增一个
server.js
,在里面使用react-router添加服务端路由,在这种情况下,部署的时候,仍旧可以把bundle.js
放到CDN上,不过index.html
要放到 express server上,这时候你必须要启动一个 express服务器,根域名指向这个express服务器,CDN只是用来存放静态资源(css,js,png等),express server 是用来相应 HTTP请求的
react router有三种对于url的策略
createHashHistory 基于锚点
createBrowserHistory 基于真实的URL,客户端这里使用
history.pushState();
相关的API进行处理,详见: https://developer.mozilla.org/en-US/docs/Web/API/History/pushStatecreateMemoryHistory 仅在内存记录,不反应URL中
你用的是2,这样的话需要服务器端也要做相应的处理,react-router官方也给了个服务端的例子:
https://github.com/rackt/react-router/blob/master/docs/guides/basics/Histories.md#createbrowserhistory
可以看一下